/* Write Base Implementation */ /// <summary> /// Writes a generic type array to a specified memory address. /// </summary> /// <typeparam name="T">An individual struct type of a class with an explicit StructLayout.LayoutKind attribute.</typeparam> /// <param name="memory"></param> /// <param name="memoryAddress">The memory address to write to.</param> /// <param name="items">The array of items to write to the address.</param> /// <param name="marshal">Set this to true to enable struct marshalling.</param> public static void Write <T>(this IMemory memory, IntPtr memoryAddress, T[] items, bool marshal = false) { IMemory oldSource = Struct.Source; Struct.Source = memory; StructArray.ToPtr(memoryAddress, items, marshal); Struct.Source = oldSource; }
/* Construction Helpers */ private void CopyVertices(ManagedSpline managedSpline) { var memory = Memory.Instance; var vertices = managedSpline.Vertices; int structSize = StructArray.GetSize <SplineVertex>(vertices.Length); VertexList = (SplineVertex *)memory.Allocate(structSize); StructArray.ToPtr((IntPtr)VertexList, vertices); }
/// <summary> /// Shows some functionality of the <see cref="Struct"/> and <see cref="StructArray"/> utility classes. /// </summary> /// <param name="memory">This object is used to perform memory read/write/free/allocate operations.</param> /// <param name="memoryLocation">Arbitrary location in memory where this tutorial will be held.</param> private static void StructUtilityExample(IMemory memory, IntPtr memoryLocation) { // Under the hood; the IMemory implementations may use a certain struct utility classes known as Struct // and StructArray which provide various methods for struct conversions and general work with structs. // Like earlier; let's load the adventure binary file. byte[] physicsData = File.ReadAllBytes($"phys.bin"); // But this time; do a direct conversion rather than reading from memory. // Note that you don't even need to specify item count this time arounnd. // This is auto-decided from array size, but can be manually overwritten. StructArray.FromArray(physicsData, out AdventurePhysics[] adventurePhysics); // Calculate total array size (in bytes). int arraySize = StructArray.GetSize <AdventurePhysics>(adventurePhysics.Length); // Get raw bytes for the struct. byte[] physicsDataBack = StructArray.GetBytes(adventurePhysics); // You can also read/write structures; as a shorthand to Memory class. StructArray.ToPtr(memoryLocation, adventurePhysics); StructArray.FromPtr(memoryLocation, out AdventurePhysics[] adventurePhysicsCopy, adventurePhysics.Length); // Beware of the double sided blade however. // A. Struct class allows you to change the source read/write source for FromPtr and ToPtr. // B. It affects both Struct and StructArray. // Note: There are also explicit overloads for FromPtr and ToPtr that let you use a source without modifying current source. Struct.Source = memory; // And of course the source is an implementation of IMemory. // Print details. if (physicsDataBack.SequenceEqual(physicsDataBack)) { Console.WriteLine($"Success: Original Physics Data and StructArray.GetBytes() are Equal"); } Console.WriteLine($"Struct Array Size: {arraySize}"); }
private void ApplyFromConfig <TGame>(Config config) where TGame : Enum { TGame[] values = (TGame[])Enum.GetValues(typeof(TGame)); AdventurePhysics[] physics = values.Select(config.GetPhysics).ToArray(); StructArray.ToPtr(PhysicsBaseAddress, physics, true); }
/* Logic */ /// <summary> /// Restores the original backup of game physics. /// </summary> public void RestorePhysics() => StructArray.ToPtr(PhysicsBaseAddress, PhysicsDump, true);