<|start_filename|>projects/Gibbed.RED4.ScriptFormats/Definitions/EnumerationDefinition.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.Collections.Generic;

namespace Gibbed.RED4.ScriptFormats.Definitions
{
    public class EnumerationDefinition : Definition
    {
        public override DefinitionType DefinitionType => DefinitionType.Enumeration;

        public EnumerationDefinition()
        {
            this.Enumerals = new List<EnumeralDefinition>();
        }

        public byte Unknown2A { get; set; }
        public byte Size { get; set; }
        public List<EnumeralDefinition> Enumerals { get; }
        public bool Unknown29 { get; set; }

        internal override void Serialize(IDefinitionWriter writer)
        {
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            writer.WriteValueU8(this.Unknown2A);
            writer.WriteValueU8(this.Size);
            writer.WriteReferences(this.Enumerals);
            writer.WriteValueB8(this.Unknown29);
        }

        internal override void Deserialize(IDefinitionReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            // TODO(gibbed): maybe visibility?
            var unknown2A = reader.ReadValueU8();
            var size = reader.ReadValueU8();
            var enumerals = reader.ReadReferences<EnumeralDefinition>();
            var unknown29 = reader.ReadValueB8();

            this.Unknown2A = unknown2A;
            this.Size = size;
            this.Enumerals.Clear();
            this.Enumerals.AddRange(enumerals);
            this.Unknown29 = unknown29;
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/DefinitionType.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

namespace Gibbed.RED4.ScriptFormats
{
    public enum DefinitionType : byte
    {
        Native = 0,
        Class = 1,
        Enumeral = 2,
        Enumeration = 3,
        Bitfield = 4,
        Function = 5,
        Parameter = 6,
        Local = 7,
        Property = 8,
        SourceFile = 9,
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/IDefinitionReader.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

namespace Gibbed.RED4.ScriptFormats
{
    internal interface IDefinitionReader
    {
        long Position { get; set; }

        bool ReadValueB8();
        sbyte ReadValueS8();
        short ReadValueS16();
        int ReadValueS32();
        long ReadValueS64();
        byte ReadValueU8();
        ushort ReadValueU16();
        uint ReadValueU32();
        ulong ReadValueU64();
        float ReadValueF32();
        double ReadValueF64();
        string ReadStringU16();
        string ReadStringU16(out ushort size);
        string ReadStringU32();
        string ReadStringU32(out uint size);
        byte[] ReadBytes();
        Definition ReadReference();
        T ReadReference<T>() where T : Definition;
        Definition[] ReadReferences();
        T[] ReadReferences<T>() where T : Definition;
        string ReadName();
        string ReadTweakDBId();
        string ReadResource();
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/Cache/CacheHeader.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.IO;
using Gibbed.IO;

namespace Gibbed.RED4.ScriptFormats.Cache
{
    internal struct CacheHeader
    {
        public const int Size = 80;

        public const int HashOffset = 12;

        public uint Unknown00;
        public uint Unknown04;
        public uint Unknown08;
        public uint HeaderHash;
        public uint Unknown10;
        public ArrayHeader StringData;
        public ArrayHeader NameStringOffsets;
        public ArrayHeader TweakDBIdStringOffsets;
        public ArrayHeader ResourceStringOffsets;
        public ArrayHeader Definitions;

        public static CacheHeader Read(Stream input, Endian endian)
        {
            CacheHeader instance;
            instance.Unknown00 = input.ReadValueU32(endian);
            instance.Unknown04 = input.ReadValueU32(endian);
            instance.Unknown08 = input.ReadValueU32(endian);
            instance.HeaderHash = input.ReadValueU32(endian);
            instance.Unknown10 = input.ReadValueU32(endian);
            instance.StringData = ArrayHeader.Read(input, endian);
            instance.NameStringOffsets = ArrayHeader.Read(input, endian);
            instance.TweakDBIdStringOffsets = ArrayHeader.Read(input, endian);
            instance.ResourceStringOffsets = ArrayHeader.Read(input, endian);
            instance.Definitions = ArrayHeader.Read(input, endian);
            return instance;
        }

        public static void Write(Stream output, CacheHeader instance, Endian endian)
        {
            output.WriteValueU32(instance.Unknown00, endian);
            output.WriteValueU32(instance.Unknown04, endian);
            output.WriteValueU32(instance.Unknown08, endian);
            output.WriteValueU32(instance.HeaderHash, endian);
            output.WriteValueU32(instance.Unknown10, endian);
            instance.StringData.Write(output, endian);
            instance.NameStringOffsets.Write(output, endian);
            instance.TweakDBIdStringOffsets.Write(output, endian);
            instance.ResourceStringOffsets.Write(output, endian);
            instance.Definitions.Write(output, endian);
        }

        public void Write(Stream output, Endian endian)
        {
            Write(output, this, endian);
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/Cache/DefinitionHeader.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.IO;
using System.Text;
using Gibbed.IO;

namespace Gibbed.RED4.ScriptFormats.Cache
{
    internal struct DefinitionHeader
    {
        public const int Size = 20;

        public uint NameIndex;
        public uint ParentIndex;
        public uint DataOffset;
        public uint DataSize;
        public DefinitionType Type;

        // TODO(gibbed): maybe uninitialized data? padding?
        public byte Unknown11;
        public byte Unknown12;
        public byte Unknown13;

        public static DefinitionHeader Read(Stream input, Endian endian)
        {
            DefinitionHeader instance;
            instance.NameIndex = input.ReadValueU32(endian);
            instance.ParentIndex = input.ReadValueU32(endian);
            instance.DataOffset = input.ReadValueU32(endian);
            instance.DataSize = input.ReadValueU32(endian);
            instance.Type = (DefinitionType)input.ReadValueU8();
            instance.Unknown11 = input.ReadValueU8();
            instance.Unknown12 = input.ReadValueU8();
            instance.Unknown13 = input.ReadValueU8();
            return instance;
        }

        public static void Write(Stream output, DefinitionHeader instance, Endian endian)
        {
            output.WriteValueU32(instance.NameIndex, endian);
            output.WriteValueU32(instance.ParentIndex, endian);
            output.WriteValueU32(instance.DataOffset, endian);
            output.WriteValueU32(instance.DataSize, endian);
            output.WriteValueU8((byte)instance.Type);
            output.WriteValueU8(instance.Unknown11);
            output.WriteValueU8(instance.Unknown12);
            output.WriteValueU8(instance.Unknown13);
        }

        public void Write(Stream output, Endian endian)
        {
            Write(output, this, endian);
        }

        public static string[] Names;

        public override string ToString()
        {
            var sb = new StringBuilder();
            if (this.ParentIndex != 0)
            {
                sb.Append($"parent={this.ParentIndex} ");
            }
            sb.Append(Enum.IsDefined(typeof(DefinitionType), this.Type) == true
                ? $"type={this.Type} "
                : $"type=unknown({this.Type}) ");
            if (this.NameIndex > 0)
            {
                sb.Append(Names != null
                    ? $"name=\"{Names[this.NameIndex]}\" "
                    : $"name_index={this.NameIndex} ");
            }
            sb.Append($"data=(@{this.DataOffset:X} {this.DataSize}) {this.Unknown11} {this.Unknown12} {this.Unknown13}");
            return sb.ToString();
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/DefinitionReader.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.IO;
using System.Text;
using Gibbed.IO;

namespace Gibbed.RED4.ScriptFormats
{
    internal class DefinitionReader : IDefinitionReader
    {
        private readonly Stream _Stream;
        private readonly Endian _Endian;
        private readonly Definition[] _Definitions;
        private readonly string[] _Names;
        private readonly string[] _TweakDBIds;
        private readonly string[] _Resources;

        public DefinitionReader(
            Stream stream,
            Endian endian,
            Definition[] definitions,
            string[] names,
            string[] tweakDBIds,
            string[] resources)
        {
            this._Stream = stream ?? throw new ArgumentNullException(nameof(stream));
            this._Endian = endian;
            this._Definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
            this._Names = names ?? throw new ArgumentNullException(nameof(names));
            this._TweakDBIds = tweakDBIds ?? throw new ArgumentNullException(nameof(tweakDBIds));
            this._Resources = resources ?? throw new ArgumentNullException(nameof(resources));
        }

        public long Position
        {
            get => this._Stream.Position;
            set => this._Stream.Position = value;
        }

        public bool ReadValueB8()
        {
            return this._Stream.ReadValueB8();
        }

        public sbyte ReadValueS8()
        {
            return this._Stream.ReadValueS8();
        }

        public short ReadValueS16()
        {
            return this._Stream.ReadValueS16(this._Endian);
        }

        public int ReadValueS32()
        {
            return this._Stream.ReadValueS32(this._Endian);
        }

        public long ReadValueS64()
        {
            return this._Stream.ReadValueS64(this._Endian);
        }

        public byte ReadValueU8()
        {
            return this._Stream.ReadValueU8();
        }

        public ushort ReadValueU16()
        {
            return this._Stream.ReadValueU16(this._Endian);
        }

        public uint ReadValueU32()
        {
            return this._Stream.ReadValueU32(this._Endian);
        }

        public ulong ReadValueU64()
        {
            return this._Stream.ReadValueU64(this._Endian);
        }

        public float ReadValueF32()
        {
            return this._Stream.ReadValueF32(this._Endian);
        }

        public double ReadValueF64()
        {
            return this._Stream.ReadValueF64(this._Endian);
        }

        public string ReadStringU16()
        {
            return this.ReadStringU16(out _);
        }

        public string ReadStringU16(out ushort size)
        {
            size = this.ReadValueU16();
            return this._Stream.ReadString(size, true, Encoding.UTF8);
        }

        public string ReadStringU32()
        {
            return this.ReadStringU32(out _);
        }

        public string ReadStringU32(out uint size)
        {
            size = this.ReadValueU32();
            if (size > int.MaxValue)
            {
                throw new FormatException();
            }
            return this._Stream.ReadString((int)size, true, Encoding.UTF8);
        }

        public byte[] ReadBytes()
        {
            var size = this.ReadValueU32();
            if (size > int.MaxValue)
            {
                throw new FormatException();
            }
            return this._Stream.ReadBytes((int)size);
        }

        public Definition ReadReference()
        {
            var index = this.ReadValueU32();
            if (index >= this._Definitions.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            return this._Definitions[index];
        }

        public T ReadReference<T>() where T : Definition
        {
            var instance = this.ReadReference();
            if (instance == null)
            {
                return null;
            }
            if (instance is T derived)
            {
                return derived;
            }
            throw new ArgumentException($"wanted {typeof(T).Name} but got {instance.GetType().Name}");
        }

        public Definition[] ReadReferences()
        {
            var count = this.ReadValueU32();
            var items = new Definition[count];
            for (uint i = 0; i < count; i++)
            {
                items[i] = this.ReadReference();
            }
            return items;
        }

        public T[] ReadReferences<T>() where T : Definition
        {
            var count = this.ReadValueU32();
            var items = new T[count];
            for (uint i = 0; i < count; i++)
            {
                items[i] = this.ReadReference<T>();
            }
            return items;
        }

        public string ReadName()
        {
            var index = this.ReadValueU32();
            if (index >= this._Names.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            return this._Names[index];
        }

        public string ReadTweakDBId()
        {
            var index = this.ReadValueU32();
            if (index >= this._TweakDBIds.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            return this._TweakDBIds[index];
        }

        public string ReadResource()
        {
            var index = this.ReadValueU32();
            if (index >= this._Resources.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            return this._Resources[index];
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/DefinitionWriter.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gibbed.IO;

namespace Gibbed.RED4.ScriptFormats
{
    internal class DefinitionWriter : IDefinitionWriter
    {
        private readonly Stream _Stream;
        private readonly Endian _Endian;
        private readonly long _BasePosition;
        private readonly Dictionary<Definition, List<long>> _Definitions;
        private readonly Dictionary<string, List<long>> _Names;
        private readonly Dictionary<string, List<long>> _TweakDBIds;
        private readonly Dictionary<string, List<long>> _Resources;

        public DefinitionWriter(IEnumerable<Definition> definitions, Stream stream, Endian endian, long basePosition = 0)
        {
            if (definitions == null)
            {
                throw new ArgumentNullException(nameof(definitions));
            }

            this._Stream = stream ?? throw new ArgumentNullException(nameof(stream));
            this._Endian = endian;
            this._BasePosition = basePosition;
            this._Definitions = new Dictionary<Definition, List<long>>();
            this._Names = new Dictionary<string, List<long>>();
            this._TweakDBIds = new Dictionary<string, List<long>>();
            this._Resources = new Dictionary<string, List<long>>();

            foreach (var definition in definitions)
            {
                this._Definitions.Add(definition, new List<long>());
                if (this._Names.ContainsKey(definition.Name) == false)
                {
                    this._Names[definition.Name] = new List<long>();
                }
            }
        }

        public long Position
        {
            get => this._Stream.Position;
            set => this._Stream.Position = value;
        }

        public void WriteValueB8(bool value)
        {
            this._Stream.WriteValueB8(value);
        }

        public void WriteValueS8(sbyte value)
        {
            this._Stream.WriteValueS8(value);
        }

        public void WriteValueS16(short value)
        {
            this._Stream.WriteValueS16(value, this._Endian);
        }

        public void WriteValueS32(int value)
        {
            this._Stream.WriteValueS32(value, this._Endian);
        }

        public void WriteValueS64(long value)
        {
            this._Stream.WriteValueS64(value, this._Endian);
        }

        public void WriteValueU8(byte value)
        {
            this._Stream.WriteValueU8(value);
        }

        public void WriteValueU16(ushort value)
        {
            this._Stream.WriteValueU16(value, this._Endian);
        }

        public void WriteValueU32(uint value)
        {
            this._Stream.WriteValueU32(value, this._Endian);
        }

        public void WriteValueU64(ulong value)
        {
            this._Stream.WriteValueU64(value, this._Endian);
        }

        public void WriteValueF32(float value)
        {
            this._Stream.WriteValueF32(value, this._Endian);
        }

        public void WriteValueF64(double value)
        {
            this._Stream.WriteValueF64(value, this._Endian);
        }

        public ushort WriteStringU16(string value)
        {
            var bytes = Encoding.UTF8.GetBytes(value);
            if (bytes.Length > ushort.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "string too long");
            }
            var size = (ushort)bytes.Length;
            this.WriteValueU16(size);
            this._Stream.WriteBytes(bytes);
            return size;
        }

        public uint WriteStringU32(string value)
        {
            var bytes = Encoding.UTF8.GetBytes(value);
            var longLength = (long)bytes.Length;
            if (longLength > uint.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "value too long");
            }
            var size = (uint)bytes.Length;
            this.WriteValueU32(size);
            this._Stream.WriteBytes(bytes);
            return size;
        }

        public void WriteBytes(byte[] value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var longLength = (long)value.Length;
            if (longLength > uint.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "value too long");
            }
            this.WriteValueU32((uint)value.Length);
            this._Stream.WriteBytes(value);
        }

        public void WriteReference(Definition value)
        {
            if (value == null)
            {
                this.WriteValueU32(0);
                return;
            }
            List<long> positions;
            if (this._Definitions.TryGetValue(value, out positions) == false)
            {
                this._Definitions[value] = positions = new List<long>();
            }
            positions.Add(this._BasePosition + this.Position);
            this.WriteValueU32(uint.MaxValue);
        }

        public void WriteReferences(IList<Definition> list)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }
            this.WriteValueS32(list.Count);
            foreach (var instance in list)
            {
                this.WriteReference(instance);
            }
        }

        public void WriteReferences<T>(IList<T> list) where T : Definition
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }
            this.WriteValueS32(list.Count);
            foreach (var instance in list)
            {
                this.WriteReference(instance);
            }
        }

        public void WriteName(string value)
        {
            List<long> positions;
            if (this._Names.TryGetValue(value, out positions) == false)
            {
                this._Names[value] = positions = new List<long>();
            }
            positions.Add(this._BasePosition + this.Position);
            this.WriteValueU32(uint.MaxValue);
        }

        public void WriteTweakDBId(string value)
        {
            List<long> positions;
            if (this._TweakDBIds.TryGetValue(value, out positions) == false)
            {
                this._TweakDBIds[value] = positions = new List<long>();
            }
            positions.Add(this._BasePosition + this.Position);
            this.WriteValueU32(uint.MaxValue);
        }

        public void WriteResource(string value)
        {
            List<long> positions;
            if (this._Resources.TryGetValue(value, out positions) == false)
            {
                this._Resources[value] = positions = new List<long>();
            }
            positions.Add(this._BasePosition + this.Position);
            this.WriteValueU32(uint.MaxValue);
        }

        public (Definition definition, long[] positions)[] GetReferencePairs()
        {
            return this._Definitions
                .Select(kv => (definition: kv.Key, positions: kv.Value.ToArray()))
                .ToArray();
        }

        public (string name, long[] positions)[] GetNamePairs()
        {
            return this._Names
                .Select(kv => (name: kv.Key, positions: kv.Value.ToArray()))
                .ToArray();
        }

        public (string tweakDBId, long[] positions)[] GetTweakDBIdPairs()
        {
            return this._TweakDBIds
                .Select(kv => (name: kv.Key, positions: kv.Value.ToArray()))
                .ToArray();
        }

        public (string resource, long[] positions)[] GetResourcePairs()
        {
            return this._Resources
                .Select(kv => (name: kv.Key, positions: kv.Value.ToArray()))
                .ToArray();
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/Cache/FileHeader.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System;
using System.IO;
using Gibbed.IO;

namespace Gibbed.RED4.ScriptFormats.Cache
{
    internal struct FileHeader
    {
        public const int Size = 12;

        public const uint Signature = 0x53444552; // 'REDS'

        public Endian Endian;
        public uint Version;
        public uint Unknown;

        public static FileHeader Read(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != Signature && magic.Swap() != Signature)
            {
                throw new FormatException();
            }
            var endian = magic == Signature ? Endian.Little : Endian.Big;

            FileHeader instance;
            instance.Endian = endian;
            instance.Version = input.ReadValueU32(endian);
            instance.Unknown = input.ReadValueU32(endian);
            return instance;
        }

        public static void Write(Stream output, FileHeader instance)
        {
            var endian = instance.Endian;
            output.WriteValueU32(Signature, endian);
            output.WriteValueU32(instance.Version, endian);
            output.WriteValueU32(instance.Unknown, endian);
        }

        public void Write(Stream output)
        {
            Write(output, this);
        }
    }
}


<|start_filename|>projects/Gibbed.RED4.ScriptFormats/IDefinitionWriter.cs<|end_filename|>
﻿/* Copyright (c) 2020 Rick (rick 'at' gibbed 'dot' us)
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would
 *    be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 */

using System.Collections.Generic;

namespace Gibbed.RED4.ScriptFormats
{
    internal interface IDefinitionWriter
    {
        long Position { get; set; }

        void WriteValueB8(bool value);
        void WriteValueS8(sbyte value);
        void WriteValueS16(short value);
        void WriteValueS32(int value);
        void WriteValueS64(long value);
        void WriteValueU8(byte value);
        void WriteValueU16(ushort value);
        void WriteValueU32(uint value);
        void WriteValueU64(ulong value);
        void WriteValueF32(float value);
        void WriteValueF64(double value);
        ushort WriteStringU16(string value);
        uint WriteStringU32(string value);
        void WriteBytes(byte[] value);
        void WriteReference(Definition value);
        void WriteReferences(IList<Definition> list);
        void WriteReferences<T>(IList<T> list)
            where T : Definition;
        void WriteName(string value);
        void WriteTweakDBId(string value);
        void WriteResource(string value);
    }
}
