Example #1
0
        /// <summary>
        /// Creates a byte array to be read by the game from a <see cref="HintFile"/>.
        /// </summary>
        public byte[] ToArray()
        {
            // Make native entries.
            var entries = new Entry[Entries.Length];

            for (int x = 0; x < entries.Length; x++)
            {
                entries[x] = new Entry(Entries[x]);
            }

            // Write strings from managed entries to a byte region.
            var stringData = new List <byte>(entries.Length * LongStringLength);

            byte[] bytes;

            for (int x = 0; x < entries.Length; x++)
            {
                entries[x].Offset = stringData.Count;
                bytes             = _encoder.GetBytes(Entries[x].Text);
                stringData.AddRange(bytes);
                stringData.Add(0);
            }

            var nullEntry       = Entry.Null;
            var nullEntryBytes  = Struct.GetBytes(ref nullEntry);
            var stringDataBytes = stringData.ToArray();

            var entryData = StructArray.GetBytes(entries);
            var allData   = new byte[entryData.Length + nullEntryBytes.Length + stringData.Count];

            Buffer.BlockCopy(entryData, 0, allData, 0, entryData.Length);
            Buffer.BlockCopy(nullEntryBytes, 0, allData, entryData.Length, nullEntryBytes.Length);
            Buffer.BlockCopy(stringDataBytes, 0, allData, entryData.Length + nullEntryBytes.Length, stringDataBytes.Length);
            return(allData);
        }
        /* Construction/Destruction */
        public RandomUInt64Generator(int megabytes)
        {
            int totalBytes = Mathematics.MegaBytesToBytes(megabytes);
            int structs    = Mathematics.BytesToStructCount <UInt64>(totalBytes);

            Structs = new UInt64[structs];

            for (int x = 0; x < structs; x++)
            {
                Structs[x] = (UInt64)NextRandom(UInt64.MinValue, UInt64.MaxValue);
            }

            Bytes = StructArray.GetBytes(Structs);
        }
        /* Construction/Destruction */
        public RandomDoubleGenerator(int megabytes)
        {
            int totalBytes = Mathematics.MegaBytesToBytes(megabytes);
            int structs    = Mathematics.BytesToStructCount <Double>(totalBytes);

            Structs = new Double[structs];

            for (int x = 0; x < structs; x++)
            {
                Structs[x] = (Double)NextRandom(Double.MinValue, Double.MaxValue);
            }

            Bytes = StructArray.GetBytes(Structs);
        }
        /* Construction/Destruction */
        public RandomInt32Generator(int megabytes)
        {
            int totalBytes = Mathematics.MegaBytesToBytes(megabytes);
            int structs    = Mathematics.BytesToStructCount <Int32>(totalBytes);

            Structs = new Int32[structs];

            for (int x = 0; x < structs; x++)
            {
                Structs[x] = (Int32)NextRandom(Int32.MinValue, Int32.MaxValue);
            }

            Bytes = StructArray.GetBytes(Structs);
        }
        /* Construction/Destruction */
        public RandomIntStructGenerator(int megabytes)
        {
            int totalBytes = Mathematics.MegaBytesToBytes(megabytes);
            int structs    = Mathematics.BytesToStructCount <RandomIntStruct>(totalBytes);

            Structs = new RandomIntStruct[structs];

            for (int x = 0; x < structs; x++)
            {
                Structs[x] = RandomIntStruct.BuildRandomStruct();
            }

            Bytes = StructArray.GetBytes(Structs);
            File.WriteAllBytes(TestFileName, Bytes);
        }
        /* Construction/Destruction */
        public RandomIntegerGenerator(int megabytes)
        {
            int totalBytes = Mathematics.MegaBytesToBytes(megabytes);
            int structs    = Mathematics.BytesToStructCount <int>(totalBytes);

            Structs = new int[structs];

            for (int x = 0; x < structs; x++)
            {
                Structs[x] = _random.Next();
            }

            Bytes = StructArray.GetBytes(Structs);
            File.WriteAllBytes(TestFileName, Bytes);
        }
Example #7
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}");
        }
Example #8
0
 /// <summary>
 /// Appends an managed/marshalled structure onto the <see cref="MemoryStream"/> and advances the position.
 /// </summary>
 public void Append <T>(T[] structure, bool marshalStructure = true) => Append(StructArray.GetBytes(structure, marshalStructure));
Example #9
0
 /// <summary>
 /// Appends an unmanaged structure onto the <see cref="MemoryStream"/> and advances the position.
 /// </summary>
 public void Append <T>(T[] structure) where T : unmanaged => Append(StructArray.GetBytes(structure));
        /// <summary>
        /// Converts a <see cref="MotionPackage"/> into a native .MTP file.
        /// </summary>
        public byte[] ToMtp()
        {
            var bytes = new List <byte>(1000000);

            var header = Header;

            header.SwapEndian();
            bytes.AddRange(Struct.GetBytes(ref header));

            // Write entries
            var dummyAnimationEntry      = new AnimationEntry();
            var dummyAnimationEntryBytes = Struct.GetBytes(ref dummyAnimationEntry);

            int[] entryOffsets = Entries.Select(x => AddRange(bytes, dummyAnimationEntryBytes)).ToArray();

            // Write file names.
            int[] fileNameOffsets = Entries.Select(x =>
            {
                int firstRef = AddRange(bytes, String.GetNullTerminatedBytes(String.Win1252Encoder, x.FileName));
                // Must pad to next group of 4-bytes, otherwise game will fail to parse
                while (bytes.Count % 4 > 0)
                {
                    bytes.Add(0x00);
                }
                return(firstRef);
            }).ToArray();

            // Write file data.
            int[] fileDataOffsets = Entries.Select(x => AddRange(bytes, x.FileData)).ToArray();

            // Write extra properties.
            int[] filePropertyOffsets = Entries.Select(x =>
            {
                if (x.Tuples != null)
                {
                    // Temporarily swap out the endian of all tuples before writing to array, then swap back.
                    for (int i = 0; i < x.Tuples.Length; i++)
                    {
                        x.Tuples[i].SwapEndian();
                    }

                    var result = AddRange(bytes, StructArray.GetBytes(x.Tuples));

                    for (int i = 0; i < x.Tuples.Length; i++)
                    {
                        x.Tuples[i].SwapEndian();
                    }

                    return(result);
                }

                return(0);
            }).ToArray();

            // Fix Offsets
            var byteArray = bytes.ToArray();

            fixed(byte *byteArrayPtr = byteArray)
            {
                for (int x = 0; x < Entries.Length; x++)
                {
                    ref var entry = ref Unsafe.AsRef <AnimationEntry>(byteArrayPtr + entryOffsets[x]);
                    Endian.Reverse(ref fileNameOffsets[x]);
                    Endian.Reverse(ref fileDataOffsets[x]);
                    Endian.Reverse(ref filePropertyOffsets[x]);

                    entry.FileNamePtr      = fileNameOffsets[x];
                    entry.FileDataPtr      = fileDataOffsets[x];
                    entry.PropertyTuplePtr = filePropertyOffsets[x];
                }
            }
 public void Write <T>(T[] structure, bool marshalStructure = true) => Write(StructArray.GetBytes(structure, marshalStructure));
 public void Write <T>(T[] structure) where T : unmanaged => Write(StructArray.GetBytes(structure));