/* Read Base Implementation */

        /// <summary>
        /// Reads a generic type array from a specified memory address.
        /// </summary>
        /// <typeparam name="T">An individual struct type of a class with an explicit StructLayout.LayoutKind attribute.</typeparam>
        /// <param name="value">Local variable to receive the read in struct array.</param>
        /// <param name="memory"></param>
        /// <param name="memoryAddress">The memory address to read from.</param>
        /// <param name="arrayLength">The amount of array items to read.</param>
        /// <param name="marshal">Set this to true to enable struct marshalling.</param>
        public static void Read <T>(this IMemory memory, IntPtr memoryAddress, out T[] value, int arrayLength, bool marshal = false)
        {
            IMemory oldSource = Struct.Source;

            Struct.Source = memory;

            value = new T[arrayLength];
            StructArray.FromPtr(memoryAddress, out value, arrayLength, marshal);

            Struct.Source = oldSource;
        }
Ejemplo n.º 2
0
        /* Read Base Implementation */

        /// <summary>
        /// Reads a generic type array from a specified memory address.
        /// </summary>
        /// <typeparam name="T">An individual struct type of a class with an explicit StructLayout.LayoutKind attribute.</typeparam>
        /// <param name="value">Local variable to receive the read in struct array.</param>
        /// <param name="memory"></param>
        /// <param name="memoryAddress">The memory address to read from.</param>
        /// <param name="arrayLength">The amount of array items to read.</param>
        /// <param name="marshal">Set this to true to enable struct marshalling.</param>
        public static void Read <T>(this IMemory memory, IntPtr memoryAddress, out T[] value, int arrayLength, bool marshal = false)
        {
            IMemory oldSource = Struct.Source;

            Struct.Source = memory;

#if NET5_0_OR_GREATER
            value = GC.AllocateUninitializedArray <T>(arrayLength, false);
#else
            value = new T[arrayLength];
#endif
            StructArray.FromPtr(memoryAddress, out value, arrayLength, marshal);

            Struct.Source = oldSource;
        }
Ejemplo n.º 3
0
        /// <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}");
        }
Ejemplo n.º 4
0
        private void XpAdded(int esi)
        {
            // Get the xp address (has to be done after the game has initialised)
            if (_xpAddress == IntPtr.Zero)
            {
                _memory.SafeRead(_statsPtr, out _xpAddress);
                _xpAddress += 0xE0;
                _utils.LogDebug($"The xp info starts at 0x{_xpAddress:X}");
            }

            // Get the in party address (has to be done after the game has initialised)
            if (_partyAddress == IntPtr.Zero)
            {
                _memory.SafeRead(_partyPtr, out _partyAddress);
                _partyAddress += 4;
                _utils.LogDebug($"The in party info starts at 0x{_partyAddress:X}");
            }

            // Get the day address (has to be done after the game has initialised)
            if (_dayAddress == IntPtr.Zero)
            {
                _memory.SafeRead(_dayPtr, out _dayAddress);
                _utils.LogDebug($"The day is at 0x{_dayAddress:X}");
            }

            try
            {
                _utils.LogDebug("Xp added starting");
                // Get how much xp was added
                _memory.SafeRead((IntPtr)(esi + 120), out int amountAdded);
                _utils.LogDebug("The protagonist gained " + amountAdded + " xp");
                int amountToAdd = (int)Math.Round(amountAdded * Math.Abs(Configuration.xpScale));
                if (amountToAdd == 0)
                {
                    return;
                }

                // Get who is in the party
                StructArray.FromPtr(_partyAddress, out short[] inParty, 3);
                _utils.LogDebug("These are in the party: " + MemberNames[inParty[0]] + ", " + MemberNames[inParty[1]] + ", " + MemberNames[inParty[2]]);

                // Get the current day and use that to determine who is unlocked
                _memory.SafeRead((IntPtr)_dayAddress, out short day);
                var unlockedParty = new List <short>();

                // Yosuke
                if (day >= 17)
                {
                    unlockedParty.Add(2);
                }

                // Chie
                if (day >= 18)
                {
                    unlockedParty.Add(3);
                }

                // Yukiko
                if (day >= 30)
                {
                    unlockedParty.Add(4);
                }

                // Kanji
                if (day >= 66)
                {
                    unlockedParty.Add(6);
                }

                // Teddie
                if (day >= 101)
                {
                    unlockedParty.Add(8);
                }

                // Naoto
                if (day >= 189)
                {
                    unlockedParty.Add(7);
                }

                // Work out which members are therefore eligible to get xp
                short[] inactiveParty = unlockedParty.Except(inParty).ToArray();

                // Add xp to them
                foreach (short member in inactiveParty)
                {
                    // If there isn't a full party there will be zeroes instead of member ids so ignore them
                    if (member <= 0)
                    {
                        continue;
                    }

                    // Get their current xp
                    _memory.SafeRead(_xpAddress + (member - 2) * 132, out int currentXp);
                    // Add the xp
                    // Xp location is the location of Yosuke's so remove 2 (Yosuke's id) from id
                    _memory.SafeWrite(_xpAddress + (member - 2) * 132, currentXp + amountToAdd);
                    _utils.LogDebug("Added " + amountToAdd + " xp to " + MemberNames[member]);
                }
            }
            catch (Exception exception)
            {
                _utils.LogError("There was an error whilst trying to add xp", exception);
            }
        }
Ejemplo n.º 5
0
 private void DumpPhysics <TGame>(out AdventurePhysics[] physics) where TGame : Enum
 {
     StructArray.FromPtr(PhysicsBaseAddress, out physics, Enum.GetValues(typeof(TGame)).Length, true);
 }