/// <summary>
        /// Reads a <see cref="System.Decimal"/> value.
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal decimal ReadPrimitive_Decimal(Stream stream)
        {
            const int elementSize = sizeof(decimal);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
#if NETSTANDARD2_0 || NETSTANDARD2_1 || NET461
            Buffer.BlockCopy(TempBuffer_Buffer, 0, TempBuffer_Int32, 0, elementSize);
            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[0]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[1]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[2]);
                EndiannessHelper.SwapBytes(ref TempBuffer_Int32[3]);
            }

            return(new decimal(TempBuffer_Int32));
#elif NET5_0_OR_GREATER
            var intBuffer = MemoryMarshal.Cast <byte, int>(TempBuffer_Buffer.AsSpan(0, elementSize));
            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref intBuffer[0]);
                EndiannessHelper.SwapBytes(ref intBuffer[1]);
                EndiannessHelper.SwapBytes(ref intBuffer[2]);
                EndiannessHelper.SwapBytes(ref intBuffer[3]);
            }

            return(new decimal(intBuffer));
#else
                        #error Unhandled .NET framework
#endif
        }
        public override void Read(EndianBinaryReader reader, ISection section = null)
        {
            reader.PushBaseOffset();

            int signature = reader.ReadInt32();

            if (signature != 0x03505854)
            {
                reader.Endianness = Endianness = Endianness.Big;
                signature         = EndiannessHelper.Swap(signature);
            }

            if (signature != 0x03505854)
            {
                throw new InvalidDataException("Invalid signature (expected TXP with type 3)");
            }

            int textureCount            = reader.ReadInt32();
            int textureCountWithRubbish = reader.ReadInt32();

            Textures.Capacity = textureCount;

            for (int i = 0; i < textureCount; i++)
            {
                reader.ReadOffset(() => { Textures.Add(new Texture(reader)); });
            }

            reader.PopBaseOffset();
        }
        public override void Write(long value)
        {
            if (EndiannessHelper.Swap(value) != value)
            {
                SetBitArrayValue(Position - mBeginPosition, ( int )ValueType.Int64);
            }

            base.Write(value);
        }
예제 #4
0
        public override void Write(long value)
        {
            if (EndiannessHelper.Swap(value) != value)
            {
                mPositionMap[Position] = sizeof(long);
            }

            base.Write(value);
        }
 private void SwapHeader(ref BinaryHeader header)
 {
     EndiannessHelper.Swap(ref header.UserId);
     EndiannessHelper.Swap(ref header.FileSize);
     EndiannessHelper.Swap(ref header.Field0C);
     EndiannessHelper.Swap(ref header.RelocationTable.Offset);
     EndiannessHelper.Swap(ref header.RelocationTableSize);
     EndiannessHelper.Swap(ref header.DialogCount);
     EndiannessHelper.Swap(ref header.Field1E);
 }
예제 #6
0
        public static T ToStruct <T>(this byte[] bytes)
        {
            EndiannessHelper.RespectEndianness(typeof(T), bytes);
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);

            try
            {
                return((T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)));
            }
            finally
            {
                handle.Free();
            }
        }
예제 #7
0
        private int ReadSegmentLength()
        {
            int segmentLength = mReader.ReadInt32();

            if (segmentLength > mReader.BaseStreamLength || segmentLength < 0)
            {
                mReader.Endianness = mReader.Endianness == Endianness.LittleEndian
                    ? Endianness.BigEndian
                    : Endianness.LittleEndian;

                segmentLength = EndiannessHelper.Swap(segmentLength);
            }

            return(segmentLength);
        }
        /// <summary>
        /// Reads a <see cref="System.DateTime"/> object.
        /// </summary>
        /// <param name="stream">Stream to read the DateTime object from.</param>
        /// <returns>The read <see cref="System.DateTime"/> object.</returns>
        internal DateTime ReadPrimitive_DateTime(Stream stream)
        {
            const int elementSize = sizeof(long);             // binary representation of a DateTime
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            long value = MemoryMarshal.Read <long>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(DateTime.FromBinary(value));
        }
        /// <summary>
        /// Reads a <see cref="System.Char"/> value (native encoding).
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal char ReadPrimitive_Char_Native(Stream stream)
        {
            const int bytesToRead = 2;
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, bytesToRead);

            if (bytesRead < bytesToRead)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            char value = MemoryMarshal.Read <char>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(value);
        }
        /// <summary>
        /// Reads a <see cref="System.Double"/> value.
        /// </summary>
        /// <param name="stream">Stream to read the value from.</param>
        /// <returns>The read value.</returns>
        internal double ReadPrimitive_Double(Stream stream)
        {
            const int elementSize = sizeof(double);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            double value = MemoryMarshal.Read <double>(TempBuffer_Buffer);

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref value);
            }
            return(value);
        }
예제 #11
0
        public static byte[] ToBytes <T>(this T data)
        {
            byte[]   bytes  = new byte[Marshal.SizeOf(data)];
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);

            try
            {
                IntPtr rawDataPtr = handle.AddrOfPinnedObject();
                Marshal.StructureToPtr(data, rawDataPtr, false);
            }
            finally
            {
                handle.Free();
            }

            EndiannessHelper.RespectEndianness(typeof(T), bytes);

            return(bytes);
        }
        /// <summary>
        /// Reads a <see cref="System.DateTimeOffset"/> object.
        /// </summary>
        /// <param name="stream">Stream to read the DateTimeOffset object from.</param>
        /// <returns>The read <see cref="System.DateTimeOffset"/> object.</returns>
        internal DateTimeOffset ReadPrimitive_DateTimeOffset(Stream stream)
        {
            const int elementSize = 2 * sizeof(long);
            int       bytesRead   = stream.Read(TempBuffer_Buffer, 0, elementSize);

            if (bytesRead < elementSize)
            {
                throw new SerializationException("Unexpected end of stream.");
            }
            long dateTimeTicks       = MemoryMarshal.Read <long>(TempBuffer_Buffer);
            long timezoneOffsetTicks = MemoryMarshal.Read <long>(TempBuffer_Buffer.AsSpan().Slice(8));

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                EndiannessHelper.SwapBytes(ref dateTimeTicks);
                EndiannessHelper.SwapBytes(ref timezoneOffsetTicks);
            }

            return(new DateTimeOffset(dateTimeTicks, new TimeSpan(timezoneOffsetTicks)));
        }
        /// <summary>
        /// Reads a <see cref="System.String"/> object (UTF-16 encoding).
        /// </summary>
        /// <param name="stream">Stream to read the string object from.</param>
        /// <returns>The read string.</returns>
        internal unsafe string ReadPrimitive_String_UTF16(Stream stream)
        {
            // read the number of UTF-16 code units
            int codeUnitCount = Leb128EncodingHelper.ReadInt32(stream);
            int size          = codeUnitCount * sizeof(char);

            // read encoded string
            EnsureTemporaryByteBufferSize(size);
            int bytesRead = stream.Read(TempBuffer_Buffer, 0, size);

            if (bytesRead < size)
            {
                throw new SerializationException("Unexpected end of stream.");
            }

            // swap bytes to fix endianness issues, if necessary
            var buffer = MemoryMarshal.Cast <byte, char>(TempBuffer_Buffer.AsSpan(0, bytesRead));

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                for (int i = 0; i < buffer.Length; i++)
                {
                    EndiannessHelper.SwapBytes(ref buffer[i]);
                }
            }

            // create a string from the buffer
#if NETSTANDARD2_0 || NET461
            string s;
            fixed(char *p = buffer)
            {
                s = new string(p, 0, buffer.Length);
            }
#elif NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
            string s = new string(buffer);
#else
                        #error Unhandled .NET framework
#endif
            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, s);
            return(s);
        }
예제 #14
0
        public override void Read(EndianBinaryReader reader, ISection section = null)
        {
            if (section != null)
            {
                ReadModern();
            }
            else
            {
                ReadClassic();
            }

            void ReadClassic()
            {
                var offsets = new List <long>();

                // Try to determine endianness (apparently DT uses big endian string arrays)
                uint stringOffset = reader.ReadUInt32();

                if (stringOffset >= reader.Length)
                {
                    reader.Endianness = Endianness.Big;
                    stringOffset      = EndiannessHelper.Swap(stringOffset);
                }

                Endianness = reader.Endianness;

                do
                {
                    offsets.Add(stringOffset);
                    stringOffset = reader.ReadUInt32();
                } while (reader.Position < offsets[0] && stringOffset != 0);

                Strings.Capacity = offsets.Count;

                for (int i = 0; i < offsets.Count; i++)
                {
                    long offset = offsets[i];
                    reader.SeekBegin(offset);

                    string value = reader.ReadString(StringBinaryFormat.NullTerminated);
                    if (!string.IsNullOrEmpty(value))
                    {
                        Strings.Add(new StringEntry {
                            Value = value, Id = ( uint )i
                        });
                    }
                }
            }

            void ReadModern()
            {
                int count = reader.ReadInt32();

                reader.ReadOffset(() =>
                {
                    Strings.Capacity = count;

                    for (int i = 0; i < count; i++)
                    {
                        Strings.Add(new StringEntry
                        {
                            Value = reader.ReadStringOffset(StringBinaryFormat.NullTerminated),
                            Id    = reader.ReadUInt32()
                        });
                    }
                });
            }
        }
예제 #15
0
        private static bool IsValidArchiveVersion2And3(Stream stream, int entrySize)
        {
            // check stream length
            if (stream.Length <= 4 + entrySize)
            {
                return(false);
            }

            byte[] testData = new byte[4 + entrySize];
            stream.Read(testData, 0, 4 + entrySize);
            stream.Position = 0;

            int numOfFiles = BitConverter.ToInt32(testData, 0);

            // num of files sanity check
            if (numOfFiles > 1024 || numOfFiles < 1 || (numOfFiles * entrySize) > stream.Length)
            {
                numOfFiles = EndiannessHelper.Swap(numOfFiles);

                if (numOfFiles > 1024 || numOfFiles < 1 || (numOfFiles * entrySize) > stream.Length)
                {
                    return(false);
                }
            }

            // check if the name field is correct
            bool nameTerminated = false;

            for (int i = 0; i < entrySize - 4; i++)
            {
                if (testData[4 + i] == 0x00)
                {
                    if (i == 0)
                    {
                        return(false);
                    }

                    nameTerminated = true;
                }

                if (testData[4 + i] != 0x00 && nameTerminated)
                {
                    return(false);
                }
            }

            // first entry length sanity check
            int length = BitConverter.ToInt32(testData, entrySize);

            if (length >= stream.Length || length < 0)
            {
                length = EndiannessHelper.Swap(length);

                if (length >= stream.Length || length < 0)
                {
                    return(false);
                }
            }

            return(true);
        }