From 7f2dde46ba01fec26c2ccdfae5cfed33fecde869 Mon Sep 17 00:00:00 2001 From: Neodymium Date: Wed, 18 Jan 2017 18:28:16 +0100 Subject: [PATCH] Improved PSO to XML, dropped XML to PSO support --- RageLib.GTA5/PSO/PsoDefinitionSection.cs | 57 +- RageLib.GTA5/PSO/PsoFile.cs | 6 + .../PSOWrappers/Data/PsoDataReader.cs | 98 +++ RageLib.GTA5/PSOWrappers/PsoReader.cs | 96 +-- RageLib.GTA5/PSOWrappers/PsoTypeBuilder.cs | 354 +++++++++++ RageLib.GTA5/PSOWrappers/PsoWriter.cs | 307 ---------- RageLib.GTA5/PSOWrappers/PsoXmlExporter.cs | 566 ++++++++++++++---- RageLib.GTA5/PSOWrappers/PsoXmlImporter.cs | 424 ------------- RageLib.GTA5/PSOWrappers/Types/IPsoValue.cs | 3 +- RageLib.GTA5/PSOWrappers/Types/PsoArray0.cs | 104 ++++ RageLib.GTA5/PSOWrappers/Types/PsoArray1.cs | 62 ++ RageLib.GTA5/PSOWrappers/Types/PsoArray4.cs | 62 ++ .../Types/{PsoType21.cs => PsoBoolean.cs} | 10 +- .../Types/{PsoType2.cs => PsoByte.cs} | 9 +- RageLib.GTA5/PSOWrappers/Types/PsoEnumByte.cs | 58 ++ RageLib.GTA5/PSOWrappers/Types/PsoEnumInt.cs | 58 ++ .../PSOWrappers/Types/PsoFlagsByte.cs | 58 ++ RageLib.GTA5/PSOWrappers/Types/PsoFlagsInt.cs | 58 ++ .../PSOWrappers/Types/PsoFlagsShort.cs | 58 ++ RageLib.GTA5/PSOWrappers/Types/PsoFloat.cs | 6 +- RageLib.GTA5/PSOWrappers/Types/PsoFloat2.cs | 47 ++ RageLib.GTA5/PSOWrappers/Types/PsoFloat3.cs | 49 ++ RageLib.GTA5/PSOWrappers/Types/PsoFloat4A.cs | 48 ++ RageLib.GTA5/PSOWrappers/Types/PsoFloat4B.cs | 51 ++ .../Types/{PsoType15.cs => PsoIntSigned.cs} | 12 +- .../Types/{PsoType6.cs => PsoIntUnsigned.cs} | 17 +- RageLib.GTA5/PSOWrappers/Types/PsoMap.cs | 108 ++++ RageLib.GTA5/PSOWrappers/Types/PsoString0.cs | 64 ++ RageLib.GTA5/PSOWrappers/Types/PsoString1.cs | 63 ++ RageLib.GTA5/PSOWrappers/Types/PsoString2.cs | 63 ++ .../Types/{PsoArray.cs => PsoString3.cs} | 70 ++- .../Types/{PsoType14.cs => PsoString7.cs} | 14 +- RageLib.GTA5/PSOWrappers/Types/PsoString8.cs | 53 ++ .../PSOWrappers/Types/PsoStructure.cs | 185 ++---- .../PSOWrappers/Types/PsoStructure3.cs | 93 +++ RageLib.GTA5/PSOWrappers/Types/PsoType11.cs | 99 --- .../Types/{PsoType16.cs => PsoType3.cs} | 11 +- RageLib.GTA5/PSOWrappers/Types/PsoType32.cs | 46 ++ .../Types/{PsoType0.cs => PsoType4.cs} | 12 +- RageLib.GTA5/PSOWrappers/Types/PsoType5.cs | 7 +- RageLib.GTA5/PSOWrappers/Types/PsoType9.cs | 48 ++ RageLib.GTA5/PSOWrappers/Types/PsoXXByte.cs | 45 ++ RageLib.GTA5/PSOWrappers/Types/PsoXXHalf.cs | 45 ++ RageLib.GTA5/RageLib.GTA5.csproj | 75 ++- Tools/MetaTool/Program.cs | 36 +- 45 files changed, 2501 insertions(+), 1314 deletions(-) create mode 100644 RageLib.GTA5/PSOWrappers/Data/PsoDataReader.cs create mode 100644 RageLib.GTA5/PSOWrappers/PsoTypeBuilder.cs delete mode 100644 RageLib.GTA5/PSOWrappers/PsoWriter.cs delete mode 100644 RageLib.GTA5/PSOWrappers/PsoXmlImporter.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoArray0.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoArray1.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoArray4.cs rename RageLib.GTA5/PSOWrappers/Types/{PsoType21.cs => PsoBoolean.cs} (86%) rename RageLib.GTA5/PSOWrappers/Types/{PsoType2.cs => PsoByte.cs} (86%) create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoEnumByte.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoEnumInt.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFlagsByte.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFlagsInt.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFlagsShort.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFloat2.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFloat3.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFloat4A.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoFloat4B.cs rename RageLib.GTA5/PSOWrappers/Types/{PsoType15.cs => PsoIntSigned.cs} (87%) rename RageLib.GTA5/PSOWrappers/Types/{PsoType6.cs => PsoIntUnsigned.cs} (81%) create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoMap.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoString0.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoString1.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoString2.cs rename RageLib.GTA5/PSOWrappers/Types/{PsoArray.cs => PsoString3.cs} (57%) rename RageLib.GTA5/PSOWrappers/Types/{PsoType14.cs => PsoString7.cs} (84%) create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoString8.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoStructure3.cs delete mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoType11.cs rename RageLib.GTA5/PSOWrappers/Types/{PsoType16.cs => PsoType3.cs} (84%) create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoType32.cs rename RageLib.GTA5/PSOWrappers/Types/{PsoType0.cs => PsoType4.cs} (84%) create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoType9.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoXXByte.cs create mode 100644 RageLib.GTA5/PSOWrappers/Types/PsoXXHalf.cs diff --git a/RageLib.GTA5/PSO/PsoDefinitionSection.cs b/RageLib.GTA5/PSO/PsoDefinitionSection.cs index 2f3c929b..af3c52a7 100644 --- a/RageLib.GTA5/PSO/PsoDefinitionSection.cs +++ b/RageLib.GTA5/PSO/PsoDefinitionSection.cs @@ -36,7 +36,7 @@ public class PsoDefinitionSection public List Entries; public void Read(DataReader reader) - { + { Ident = reader.ReadInt32(); var Length = reader.ReadInt32(); this.Count = reader.ReadUInt32(); @@ -80,17 +80,17 @@ public void Write(DataWriter writer) var entriesWriter = new DataWriter(entriesStream, Endianess.BigEndian); for (int i = 0; i < Entries.Count; i++) { - EntriesIdx[i].Offset = 12 + 8* Entries.Count + (int)entriesWriter.Position; + EntriesIdx[i].Offset = 12 + 8 * Entries.Count + (int)entriesWriter.Position; Entries[i].Write(entriesWriter); } - + var indexStream = new MemoryStream(); var indexWriter = new DataWriter(indexStream, Endianess.BigEndian); foreach (var entry in EntriesIdx) - entry.Write(indexWriter); - + entry.Write(indexWriter); + @@ -110,7 +110,7 @@ public void Write(DataWriter writer) entriesStream.Read(buf2, 0, buf2.Length); writer.Write(buf2); - + } } @@ -146,7 +146,7 @@ public class PsoStructureInfo : PsoElementInfo public byte Unk { get; set; } public int StructureLength { get; set; } public uint Unk_Ch { get; set; } = 0x00000000; - public List Entries { get; set; } + public List Entries { get; set; } = new List(); public override void Read(DataReader reader) { @@ -185,25 +185,25 @@ public override void Write(DataWriter writer) public enum DataType : byte { - BYTE_00h = 0x00, + Boolean = 0x00, LONG_01h = 0x01, - BYTE_02h = 0x02, + Byte = 0x02, SHORT_03h = 0x03, SHORT_04h = 0x04, INT_05h = 0x05, - INT_06h = 0x06, + Integer = 0x06, Float = 0x07, - LONG_08h = 0x08, + Float2 = 0x08, TYPE_09h = 0x09, - TYPE_0Ah = 0x0a, - INT_0Bh = 0x0b, + Float4 = 0x0a, + String = 0x0b, Structure = 0x0c, Array = 0x0d, - BYTE_ENUM_VALUE = 0x0e, - SHORT_0Fh = 0x0f, - TYPE_10h = 0x10, + Enum = 0x0e, + Flags = 0x0f, + Map = 0x10, TYPE_14h = 0x14, - TYPE_15h = 0x15, + Float3 = 0x15, SHORT_1Eh = 0x1e, LONG_20h = 0x20 } @@ -216,13 +216,25 @@ public class PsoStructureEntryInfo public short DataOffset; public int ReferenceKey; // when array -> entry index with type + public PsoStructureEntryInfo() + { } + + public PsoStructureEntryInfo(int nameHash, DataType type, byte unk5, short dataOffset, int referenceKey) + { + this.EntryNameHash = nameHash; + this.Type = type; + this.Unk_5h = unk5; + this.DataOffset = dataOffset; + this.ReferenceKey = referenceKey; + } + public void Read(DataReader reader) { this.EntryNameHash = reader.ReadInt32(); this.Type = (DataType)reader.ReadByte(); this.Unk_5h = reader.ReadByte(); this.DataOffset = reader.ReadInt16(); - this.ReferenceKey = reader.ReadInt32(); + this.ReferenceKey = reader.ReadInt32(); } public void Write(DataWriter writer) @@ -277,6 +289,15 @@ public class PsoEnumEntryInfo public int EntryNameHash { get; set; } public int EntryKey { get; set; } + public PsoEnumEntryInfo() + { } + + public PsoEnumEntryInfo(int nameHash, int key) + { + this.EntryNameHash = nameHash; + this.EntryKey = key; + } + public void Read(DataReader reader) { this.EntryNameHash = reader.ReadInt32(); diff --git a/RageLib.GTA5/PSO/PsoFile.cs b/RageLib.GTA5/PSO/PsoFile.cs index c1161149..baeed7c3 100644 --- a/RageLib.GTA5/PSO/PsoFile.cs +++ b/RageLib.GTA5/PSO/PsoFile.cs @@ -101,6 +101,12 @@ public virtual void Save(Stream stream) + public static bool IsPSO(string fileName) + { + using (var stream = new FileStream(fileName, FileMode.Open)) + return !IsRBF(stream); + } + public static bool IsPSO(Stream stream) { return !IsRBF(stream); diff --git a/RageLib.GTA5/PSOWrappers/Data/PsoDataReader.cs b/RageLib.GTA5/PSOWrappers/Data/PsoDataReader.cs new file mode 100644 index 00000000..3b161b94 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Data/PsoDataReader.cs @@ -0,0 +1,98 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using RageLib.GTA5.PSO; + +namespace RageLib.GTA5.PSOWrappers.Data +{ + public class PsoDataReader : DataReader + { + private readonly PsoFile psoFile; + + public override long Length + { + get + { + return psoFile.DataMappingSection.Entries[CurrentSectionIndex].Length; + } + } + + public int CurrentSectionIndex + { + get; + private set; + } + + public int CurrentSectionHash + { + get; + private set; + } + + public override long Position + { + get; + set; + } + + + + public PsoDataReader(PsoFile psoFile) : base(null, Endianess.BigEndian) + { + this.psoFile = psoFile; + } + + protected override byte[] ReadFromStream(int count, bool ignoreEndianess = false) + { + // TODO very bad performance, improve this! + var str = new MemoryStream(psoFile.DataSection.Data); + str.Position = psoFile.DataMappingSection.Entries[CurrentSectionIndex].Offset; + str.Position += Position; + + var buffer = new byte[count]; + str.Read(buffer, 0, count); + + Position += count; + + // handle endianess + if (!ignoreEndianess && (Endianess == Endianess.BigEndian)) + { + Array.Reverse(buffer); + } + + return buffer; + } + + public void SetSectionIndex(int index) + { + CurrentSectionIndex = index; + CurrentSectionHash = psoFile.DataMappingSection.Entries[index].NameHash; + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/PsoReader.cs b/RageLib.GTA5/PSOWrappers/PsoReader.cs index 1f241f33..3a72ca4f 100644 --- a/RageLib.GTA5/PSOWrappers/PsoReader.cs +++ b/RageLib.GTA5/PSOWrappers/PsoReader.cs @@ -20,8 +20,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -using RageLib.Data; using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; using RageLib.GTA5.PSOWrappers.Types; using System.Collections.Generic; using System.IO; @@ -50,100 +50,24 @@ public IPsoValue Parse(PsoFile meta) var blockKeys = new List(); var blocks = new List>(); - - var resultStructure = new PsoStructure(); - resultStructure.pso = meta; - + var t1 = (PsoStructureInfo)null; + var t2 = (PsoElementIndexInfo)null; var rootHash = meta.DataMappingSection.Entries[meta.DataMappingSection.RootIndex - 1].NameHash; for (int i = 0; i < meta.DefinitionSection.Count; i++) { if (meta.DefinitionSection.EntriesIdx[i].NameHash == rootHash) { - resultStructure.psoSection = (PsoStructureInfo)meta.DefinitionSection.Entries[i]; - resultStructure.psoEntryInfo = meta.DefinitionSection.EntriesIdx[i]; + t1 = (PsoStructureInfo)meta.DefinitionSection.Entries[i]; + t2 = meta.DefinitionSection.EntriesIdx[i]; } } - var reader = new DataReader(new MemoryStream(meta.DataSection.Data), Endianess.BigEndian); - reader.Position = meta.DataMappingSection.Entries[meta.DataMappingSection.RootIndex - 1].Offset; - resultStructure.Read(reader); - - - var stack = new Stack(); - stack.Push(resultStructure); - while (stack.Count > 0) - { - var x = stack.Pop(); - foreach (var ee in x.psoSection.Entries) - { - if (ee.EntryNameHash == 0x100) - continue; - - var value = x.Values[ee.EntryNameHash]; - - if (value is PsoStructure) - { - stack.Push((PsoStructure)value); - } - if (value is PsoArray) - { - var arrayValue = (PsoArray)value; - switch (arrayValue.psoSection.Type) - { - case DataType.Structure: - { - if (arrayValue.NumberOfEntries > 0) - { - arrayValue.Entries = new List(); - reader.Position = meta.DataMappingSection.Entries[arrayValue.BlockIndex - 1].Offset + arrayValue.Offset; - for (int i = 0; i < arrayValue.NumberOfEntries; i++) - { - PsoStructure item = new PsoStructure(); - item.pso = meta; - item.psoSection = null; - for (int y = 0; y < meta.DefinitionSection.Count; y++) - { - if (meta.DefinitionSection.EntriesIdx[y].NameHash == arrayValue.psoSection.ReferenceKey) - { - item.psoSection = (PsoStructureInfo)meta.DefinitionSection.Entries[y]; - item.psoEntryInfo = meta.DefinitionSection.EntriesIdx[y]; - } - } - - item.Read(reader); - arrayValue.Entries.Add(item); - stack.Push(item); - - } - } - - break; - } - case DataType.INT_0Bh: - { - if (arrayValue.NumberOfEntries > 0) - { - arrayValue.Entries = new List(); - reader.Position = meta.DataMappingSection.Entries[arrayValue.BlockIndex - 1].Offset + arrayValue.Offset; - for (int i = 0; i < arrayValue.NumberOfEntries; i++) - { - PsoType11 item = new PsoType11(0); - item.Read(reader); - arrayValue.Entries.Add(item); - } - - } - - - break; - } - default: - throw new System.Exception("Unknown array type."); - } - } - } - } + var resultStructure = new PsoStructure(meta, t1, t2, null); + var reader = new PsoDataReader(meta); + reader.SetSectionIndex(meta.DataMappingSection.RootIndex - 1); + reader.Position = 0; + resultStructure.Read(reader); return resultStructure; } } diff --git a/RageLib.GTA5/PSOWrappers/PsoTypeBuilder.cs b/RageLib.GTA5/PSOWrappers/PsoTypeBuilder.cs new file mode 100644 index 00000000..db73a3cb --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/PsoTypeBuilder.cs @@ -0,0 +1,354 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Types; +using System; + +namespace RageLib.GTA5.PSOWrappers +{ + public static class PsoTypeBuilder + { + public static IPsoValue Make(PsoFile pso, PsoStructureInfo structureInfo, PsoStructureEntryInfo entryInfo) + { + switch (entryInfo.Type) + { + case DataType.Array: + { + switch (entryInfo.Unk_5h) + { + case 0: + { + var t = structureInfo.Entries[entryInfo.ReferenceKey & 0x0000FFFF]; + return new PsoArray0(pso, structureInfo, t); + } + case 1: + { + var typeIndex = entryInfo.ReferenceKey & 0x0000FFFF; + var num = (entryInfo.ReferenceKey >> 16) & 0x0000FFFF; + var t = structureInfo.Entries[typeIndex]; + return new PsoArray1(pso, structureInfo, t, num); + } + case 4: + { + var typeIndex = entryInfo.ReferenceKey & 0x0000FFFF; + var num = (entryInfo.ReferenceKey >> 16) & 0x0000FFFF; + var t = structureInfo.Entries[typeIndex]; + return new PsoArray4(pso, structureInfo, t, num); + } + default: + { + throw new Exception("Unsupported array type."); + } + } + } + case DataType.String: + { + switch (entryInfo.Unk_5h) + { + case 0: + { + var len = (entryInfo.ReferenceKey >> 16) & 0x0000FFFF; + return new PsoString0(len); + } + case 1: + { + return new PsoString1(); + } + case 2: + { + return new PsoString2(); + } + case 3: + { + return new PsoString3(); + } + case 7: + { + return new PsoString7(); + } + case 8: + { + return new PsoString8(); + } + default: + { + throw new Exception("Unsupported string type."); + } + } + } + case DataType.Enum: + { + switch (entryInfo.Unk_5h) + { + case 0: + { + var entryValue = new PsoEnumInt(); + entryValue.TypeInfo = GetEnumInfo(pso, entryInfo.ReferenceKey); + return entryValue; + } + case 2: + { + var entryValue = new PsoEnumByte(); + entryValue.TypeInfo = GetEnumInfo(pso, entryInfo.ReferenceKey); + return entryValue; + } + default: + { + throw new Exception("Unsupported enum type."); + } + } + } + case DataType.Flags: + { + switch (entryInfo.Unk_5h) + { + case 0: + { + var entryValue = new PsoFlagsInt(); + var sidx = entryInfo.ReferenceKey & 0x0000FFFF; + + if (sidx != 0xfff) + { + var reftype = structureInfo.Entries[sidx]; + entryValue.TypeInfo = GetEnumInfo(pso, reftype.ReferenceKey); + } + + + return entryValue; + } + case 1: + { + var entryValue = new PsoFlagsShort(); + var sidx = entryInfo.ReferenceKey & 0x0000FFFF; + + var reftype = structureInfo.Entries[sidx]; + entryValue.TypeInfo = GetEnumInfo(pso, reftype.ReferenceKey); + + return entryValue; + } + case 2: + { + var entryValue = new PsoFlagsByte(); + var sidx = entryInfo.ReferenceKey & 0x0000FFFF; + var reftype = structureInfo.Entries[sidx]; + entryValue.TypeInfo = GetEnumInfo(pso, reftype.ReferenceKey); + return entryValue; + } + default: + { + throw new Exception("Unsupported flags type."); + } + } + } + case DataType.Integer: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoIntSigned(); + case 1: return new PsoIntUnsigned(); + default: throw new Exception("Unsupported integer type."); + } + } + case DataType.Structure: + { + switch (entryInfo.Unk_5h) + { + case 0: + { + var t1 = GetStructureInfo(pso, entryInfo.ReferenceKey); + var t2 = GetStructureIndexInfo(pso, entryInfo.ReferenceKey); + var entryValue = new PsoStructure(pso, t1, t2, entryInfo); + return entryValue; + } + case 3: + { + return new PsoStructure3(pso, structureInfo, entryInfo); + } + default: + { + throw new Exception("Unsupported structure type."); + } + } + } + case DataType.Map: + { + switch (entryInfo.Unk_5h) + { + case 1: + { + var idx1 = entryInfo.ReferenceKey & 0x0000FFFF; + var idx2 = (entryInfo.ReferenceKey >> 16) & 0x0000FFFF; + var reftype1 = structureInfo.Entries[idx2]; + var reftype2 = structureInfo.Entries[idx1]; + return new PsoMap(pso, structureInfo, reftype1, reftype2); + } + default: throw new Exception("Unsupported PsoType5 type."); + } + + } + case DataType.INT_05h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoType5(); + default: throw new Exception("Unsupported PsoType5 type."); + } + } + case DataType.Byte: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoByte(); + default: throw new Exception("Unsupported PsoByte type."); + } + } + case DataType.Boolean: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoBoolean(); + default: throw new Exception("Unsupported boolean type."); + } + } + case DataType.Float: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoFloat(); + default: throw new Exception("Unsupported float type."); + } + } + case DataType.Float2: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoFloat2(); + default: throw new Exception("Unsupported float2 type."); + } + } + case DataType.Float3: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoFloat4A(); + default: throw new Exception("Unsupported float3 type."); + } + } + case DataType.Float4: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoFloat4B(); + default: throw new Exception("Unsupported float4 type."); + } + } + case DataType.TYPE_09h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoType9(); + default: throw new Exception("Unsupported PsoType9 type."); + } + } + case DataType.LONG_20h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoType32(); + default: throw new Exception("Unsupported PsoType32 type."); + } + } + case DataType.SHORT_1Eh: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoXXHalf(); + default: throw new Exception("Unsupported PsoType30 type."); + } + } + case DataType.SHORT_03h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoType3(); + default: throw new Exception("Unsupported PsoType3 type."); + } + } + case DataType.SHORT_04h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoType4(); + default: throw new Exception("Unsupported PsoType4 type."); + } + } + case DataType.LONG_01h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoXXByte(); + default: throw new Exception("Unsupported PsoType1 type."); + } + } + case DataType.TYPE_14h: + { + switch (entryInfo.Unk_5h) + { + case 0: return new PsoFloat3(); + default: throw new Exception("Unsupported PsoType20 type."); + } + } + default: + throw new Exception("Unsupported type."); + } + } + + public static PsoStructureInfo GetStructureInfo(PsoFile meta, int structureKey) + { + PsoStructureInfo info = null; + for (int i = 0; i < meta.DefinitionSection.Count; i++) + if (meta.DefinitionSection.EntriesIdx[i].NameHash == structureKey) + info = (PsoStructureInfo)meta.DefinitionSection.Entries[i]; + return info; + } + + public static PsoEnumInfo GetEnumInfo(PsoFile meta, int structureKey) + { + PsoEnumInfo info = null; + for (int i = 0; i < meta.DefinitionSection.Count; i++) + if (meta.DefinitionSection.EntriesIdx[i].NameHash == structureKey) + info = (PsoEnumInfo)meta.DefinitionSection.Entries[i]; + return info; + } + + public static PsoElementIndexInfo GetStructureIndexInfo(PsoFile meta, int structureKey) + { + PsoElementIndexInfo info = null; + for (int i = 0; i < meta.DefinitionSection.Count; i++) + if (meta.DefinitionSection.EntriesIdx[i].NameHash == structureKey) + info = (PsoElementIndexInfo)meta.DefinitionSection.EntriesIdx[i]; + return info; + } + + } +} diff --git a/RageLib.GTA5/PSOWrappers/PsoWriter.cs b/RageLib.GTA5/PSOWrappers/PsoWriter.cs deleted file mode 100644 index 49c93695..00000000 --- a/RageLib.GTA5/PSOWrappers/PsoWriter.cs +++ /dev/null @@ -1,307 +0,0 @@ -/* - Copyright(c) 2016 Neodymium - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -using RageLib.GTA5.PSO; -using RageLib.GTA5.PSOWrappers.Types; -using RageLib.GTA5.PSOWrappers.Xml; -using RageLib.GTA5.ResourceWrappers.PC.Meta.Data; -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml.Serialization; - -namespace RageLib.GTA5.PSOWrappers -{ - public class PsoWriter - { - private PsoFile meta; - private ISet usedStructureKeys = new HashSet(); - - public void Write(IPsoValue value, string fileName) - { - using (var fileStream = new FileStream(fileName, FileMode.Create)) - { - Write(value, fileStream); - } - } - - public void Write(IPsoValue value, Stream fileStream) - { - var resource = Build(value); - resource.Save(fileStream); - } - - public PsoFile Build(IPsoValue value) - { - MetaInitialize(); - MetaBuildStructuresAndEnums(); - - var writer = new MetaDataWriter(Data.Endianess.BigEndian); - writer.SelectBlockByNameHash(((PsoStructure)value).psoEntryInfo.NameHash); - WriteStructure(writer, (PsoStructure)value); - - meta.DataMappingSection.Entries = new List(); - - var ms = new MemoryStream(); - ms.Position = 16; - foreach (var block in writer.Blocks) - { - var metaDataBlock = new PsoDataMappingEntry(); - metaDataBlock.NameHash = block.NameHash; - metaDataBlock.Offset = (int)ms.Position; - metaDataBlock.Length = (int)block.Stream.Length; - - var buf = new byte[block.Stream.Length]; - block.Stream.Position = 0; - block.Stream.Read(buf, 0, buf.Length); - ms.Write(buf, 0, buf.Length); - - // fill... - buf = new byte[16 - ms.Position % 16]; - if (buf.Length != 16) - ms.Write(buf, 0, buf.Length); - - meta.DataMappingSection.Entries.Add(metaDataBlock); - } - - var totalBuf = new byte[ms.Length]; - ms.Position = 0; - ms.Read(totalBuf, 0, totalBuf.Length); - meta.DataSection.Data = totalBuf; - - for (int i = 0; i < meta.DataMappingSection.Entries.Count; i++) - { - if (meta.DataMappingSection.Entries[i].NameHash == ((PsoStructure)value).psoEntryInfo.NameHash) - { - meta.DataMappingSection.RootIndex = i + 1; - } - } - - return meta; - } - - private void MetaInitialize() - { - meta = new PsoFile(); - meta.DataMappingSection = new PsoDataMappingSection(); - meta.DataSection = new PsoDataSection(); - meta.DefinitionSection = new PsoDefinitionSection(); - } - - private void MetaBuildStructuresAndEnums() - { - var assembly = Assembly.GetExecutingAssembly(); - using (Stream xmlStream = assembly.GetManifestResourceStream("RageLib.GTA5.PSOWrappers.Xml.PsoDefinitions.xml")) - { - var ser = new XmlSerializer(typeof(PsoDefinitionXml)); - var xml = (PsoDefinitionXml)ser.Deserialize(xmlStream); - MetaBuildStructureInfos(xml); - MetaBuildEnumInfos(xml); - } - } - - private void MetaBuildStructureInfos(PsoDefinitionXml xmlInfo) - { - meta.DefinitionSection.EntriesIdx = new List(); - meta.DefinitionSection.Entries = new List(); - - foreach (var xmlStructureInfo in xmlInfo.Structures) - { - var idxInfo = new PsoElementIndexInfo(); - idxInfo.Offset = 0; - idxInfo.NameHash = xmlStructureInfo.NameHash; - - var structureInfo = new PsoStructureInfo(); - structureInfo.Type = 1; - structureInfo.Unk = (byte)xmlStructureInfo.Unknown; - structureInfo.StructureLength = xmlStructureInfo.Length; - structureInfo.Entries = new List(); - foreach (var xmlStructureEntryInfo in xmlStructureInfo.Entries) - { - var xmlArrayTypeStack = new Stack(); - var xmlArrayType = xmlStructureEntryInfo.ArrayType; - while (xmlArrayType != null) - { - xmlArrayTypeStack.Push(xmlArrayType); - xmlArrayType = xmlArrayType.ArrayType; - } - - while (xmlArrayTypeStack.Count > 0) - { - xmlArrayType = xmlArrayTypeStack.Pop(); - var arrayStructureEntryInfo = new PsoStructureEntryInfo(); - arrayStructureEntryInfo.EntryNameHash = xmlArrayType.NameHash; - arrayStructureEntryInfo.Type = (DataType)xmlArrayType.Type; - arrayStructureEntryInfo.Unk_5h = (byte)xmlArrayType.Unknown; - arrayStructureEntryInfo.DataOffset = (short)xmlArrayType.Offset; - if (arrayStructureEntryInfo.Type == DataType.Array) - { - arrayStructureEntryInfo.ReferenceKey = (short)(structureInfo.Entries.Count - 1); - } - else - { - arrayStructureEntryInfo.ReferenceKey = 0; - } - arrayStructureEntryInfo.ReferenceKey = xmlArrayType.TypeHash; - structureInfo.Entries.Add(arrayStructureEntryInfo); - } - - var structureEntryInfo = new PsoStructureEntryInfo(); - structureEntryInfo.EntryNameHash = xmlStructureEntryInfo.NameHash; - structureEntryInfo.Type = (DataType)xmlStructureEntryInfo.Type; - structureEntryInfo.Unk_5h = (byte)xmlStructureEntryInfo.Unknown; - structureEntryInfo.DataOffset = (short)xmlStructureEntryInfo.Offset; - if (structureEntryInfo.Type == DataType.Array) - { - structureEntryInfo.ReferenceKey = (short)(structureInfo.Entries.Count - 1); - } - else - { - structureEntryInfo.ReferenceKey = 0; - } - structureEntryInfo.ReferenceKey = xmlStructureEntryInfo.TypeHash; - - structureInfo.Entries.Add(structureEntryInfo); - } - - - meta.DefinitionSection.EntriesIdx.Add(idxInfo); - meta.DefinitionSection.Entries.Add(structureInfo); - } - } - - private void MetaBuildEnumInfos(PsoDefinitionXml xmlInfo) - { - foreach (var xmlEnumInfo in xmlInfo.Enums) - { - var idxInfo = new PsoElementIndexInfo(); - idxInfo.Offset = 0; - idxInfo.NameHash = xmlEnumInfo.NameHash; - - var info = new PsoEnumInfo(); - info.Entries = new List(); - foreach (var xmlEnumEntryInfo in xmlEnumInfo.Entries) - { - var enumEntryInfo = new PsoEnumEntryInfo(); - enumEntryInfo.EntryNameHash = xmlEnumEntryInfo.NameHash; - enumEntryInfo.EntryKey = xmlEnumEntryInfo.Value; - info.Entries.Add(enumEntryInfo); - } - - meta.DefinitionSection.EntriesIdx.Add(idxInfo); - meta.DefinitionSection.Entries.Add(info); - } - } - - private void WriteStructure(MetaDataWriter writer, PsoStructure value) - { - var updateStack = new Stack(); - - // build stack for update... - var structuresToCheck = new Stack(); - structuresToCheck.Push(value); - while (structuresToCheck.Count > 0) - { - var structureToCheck = structuresToCheck.Pop(); - - // add structure to list of occurring structures - usedStructureKeys.Add(structureToCheck.psoEntryInfo.NameHash); - - foreach (var structureEntryToCheck in structureToCheck.Values) - { - if (structureEntryToCheck.Value is PsoArray) - { - updateStack.Push(structureEntryToCheck.Value); - - var arrayStructureEntryToCheck = structureEntryToCheck.Value as PsoArray; - if (arrayStructureEntryToCheck.Entries != null) - { - for (int k = arrayStructureEntryToCheck.Entries.Count - 1; k >= 0; k--) - { - var x = arrayStructureEntryToCheck.Entries[k]; - if (x is PsoStructure) - { - structuresToCheck.Push(x as PsoStructure); - } - } - } - } - if (structureEntryToCheck.Value is PsoStructure) - { - structuresToCheck.Push((PsoStructure)structureEntryToCheck.Value); - } - } - } - - // update structures... - while (updateStack.Count > 0) - { - var v = updateStack.Pop(); - if (v is PsoArray) - { - var arrayValue = (PsoArray)v; - if (arrayValue.Entries != null) - { - - if (arrayValue.psoSection.Type == DataType.Structure) - { - writer.SelectBlockByNameHash((int)arrayValue.psoSection.ReferenceKey); - writer.Position = writer.Length; - } - else if (arrayValue.psoSection.Type == DataType.INT_0Bh) - { - writer.SelectBlockByNameHash(6); - writer.Position = writer.Length; - } - else - { - throw new Exception("Unknown array type."); - } - - - - - arrayValue.BlockIndex = writer.BlockIndex + 1; - arrayValue.Offset = (int)writer.Position; - arrayValue.NumberOfEntries = arrayValue.Entries.Count; - foreach (var entry in arrayValue.Entries) - { - entry.Write(writer); - } - } - else - { - arrayValue.BlockIndex = 0; - arrayValue.Offset = 0; - arrayValue.NumberOfEntries = 0; - } - } - } - - // now only the root itself is left... - writer.SelectBlockByNameHash(value.psoEntryInfo.NameHash); - writer.Position = writer.Length; - value.Write(writer); - } - } -} diff --git a/RageLib.GTA5/PSOWrappers/PsoXmlExporter.cs b/RageLib.GTA5/PSOWrappers/PsoXmlExporter.cs index a243ef66..9959c637 100644 --- a/RageLib.GTA5/PSOWrappers/PsoXmlExporter.cs +++ b/RageLib.GTA5/PSOWrappers/PsoXmlExporter.cs @@ -24,10 +24,9 @@ THE SOFTWARE. using RageLib.GTA5.PSOWrappers.Types; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; using System.Xml; namespace RageLib.GTA5.PSOWrappers @@ -56,7 +55,7 @@ public void Export(IPsoValue value, Stream xmlFileStream) var writer = new XmlTextWriter(xmlFileStream, Encoding.UTF8); writer.Formatting = Formatting.Indented; writer.WriteStartDocument(); - writer.WriteStartElement(GetNameForHash(strctureValue.psoEntryInfo.NameHash)); + writer.WriteStartElement(GetNameForHash(strctureValue.entryIndexInfo.NameHash)); WriteStructureContentXml(strctureValue, writer); writer.WriteEndElement(); writer.WriteEndDocument(); @@ -69,189 +68,530 @@ private void WriteStructureContentXml(PsoStructure value, XmlTextWriter writer) { var fieldNameHash = field.Key; var fieldValue = field.Value; - writer.WriteStartElement(GetNameForHash(fieldNameHash)); + var fixedName = GetNameForHash(fieldNameHash); + + writer.WriteStartElement(fixedName); WriteStructureElementContentXml(fieldValue, writer); writer.WriteEndElement(); } } - private void WriteStructureElementContentXml(IPsoValue value, XmlTextWriter writer) + private void WriteStructureContentXml(PsoStructure3 value, XmlTextWriter writer) { - if (value is PsoArray) + if (value.Value != null) { - var arrayValue = value as PsoArray; - if (arrayValue.Entries != null) + writer.WriteAttributeString("type", GetNameForHash(value.Value.entryIndexInfo.NameHash)); + foreach (var field in value.Value.Values) { - if (arrayValue.psoSection.Type == DataType.INT_0Bh) - { - // TODO write content... - //WriteByteArrayContent(writer, arrayValue); - - foreach (var k in arrayValue.Entries) - { - writer.WriteStartElement("Item"); - var kk = k as PsoType11; - if (kk.Value == null) - { - writer.WriteString(GetNameForHash(kk.ValueHash)); - } - else - { - writer.WriteString(kk.Value); - } - writer.WriteEndElement(); - } + var fieldNameHash = field.Key; + var fieldValue = field.Value; + var fixedName = GetNameForHash(fieldNameHash); + writer.WriteStartElement(fixedName); + WriteStructureElementContentXml(fieldValue, writer); + writer.WriteEndElement(); + } + } + } - } - else if (arrayValue.psoSection.Type == DataType.BYTE_ENUM_VALUE) - { - // TODO write content... - //WriteByteArrayContent(writer, arrayValue); + private void WriteStructureElementContentXml(IPsoValue value, XmlTextWriter writer) + { + if (value is PsoArray0) + { + WriteArrayContent(writer, (PsoArray0)value); + } + else if (value is PsoArray1) + { + WriteArrayContent(writer, (PsoArray1)value); + } + else if (value is PsoArray4) + { + WriteArrayContent(writer, (PsoArray4)value); + } + else if (value is PsoBoolean) + { + WriteBooleanContent(writer, (PsoBoolean)value); + } + else if (value is PsoByte) + { + WriteByteContent(writer, (PsoByte)value); + } + else if (value is PsoEnumByte) + { + WriteEnumContent(writer, (PsoEnumByte)value); + } + else if (value is PsoEnumInt) + { + WriteEnumContent(writer, (PsoEnumInt)value); + } + else if (value is PsoFlagsByte) + { + WriteFlagsContent(writer, (PsoFlagsByte)value); + } + else if (value is PsoFlagsShort) + { + WriteFlagsContent(writer, (PsoFlagsShort)value); + } + else if (value is PsoFlagsInt) + { + WriteFlagsContent(writer, (PsoFlagsInt)value); + } + else if (value is PsoFloat) + { + WriteFloatContent(writer, (PsoFloat)value); + } + else if (value is PsoFloat2) + { + WriteFloatContent(writer, (PsoFloat2)value); + } + else if (value is PsoFloat3) + { + WriteFloatContent(writer, (PsoFloat3)value); + } + else if (value is PsoFloat4A) + { + WriteFloatContent(writer, (PsoFloat4A)value); + } + else if (value is PsoFloat4B) + { + WriteFloatContent(writer, (PsoFloat4B)value); + } + else if (value is PsoIntSigned) + { + WriteIntegerContent(writer, (PsoIntSigned)value); + } + else if (value is PsoIntUnsigned) + { + WriteIntegerContent(writer, (PsoIntUnsigned)value); + } + else if (value is PsoMap) + { + WriteMapContent(writer, (PsoMap)value); + } + else if (value is PsoString0) + { + WriteStringContent(writer, (PsoString0)value); + } + else if (value is PsoString1) + { + WriteStringContent(writer, (PsoString1)value); + } + else if (value is PsoString2) + { + WriteStringContent(writer, (PsoString2)value); + } + else if (value is PsoString3) + { + WriteStringContent(writer, (PsoString3)value); + } + else if (value is PsoString7) + { + WriteStringContent(writer, (PsoString7)value); + } + else if (value is PsoString8) + { + WriteStringContent(writer, (PsoString8)value); + } - foreach (var k in arrayValue.Entries) - { - writer.WriteStartElement("Item"); - writer.WriteString(GetHex(((PsoType14)k).Value)); - writer.WriteEndElement(); - } + else if (value is PsoType5) + { + var v = value as PsoType5; + Write5Content(writer, v); + } + else if (value is PsoStructure) + { + var structureValue = value as PsoStructure; + WriteStructureContentXml(structureValue, writer); + } + else if (value is PsoStructure3) + { + var structureValue = value as PsoStructure3; + WriteStructureContentXml(structureValue, writer); + } + else if (value is PsoXXHalf) + { + throw new NotImplementedException(); + } + else if (value is PsoType4) + { + throw new NotImplementedException(); + } + else if (value is PsoType9) + { + throw new NotImplementedException(); + } + else if (value is PsoType32) + { + throw new NotImplementedException(); + } + else if (value is PsoType3) + { + throw new NotImplementedException(); + } + else if (value is PsoXXByte) + { + throw new NotImplementedException(); + } + else + { + throw new Exception("Unknown type"); + } + } + + + + + + private void WriteArrayContent(XmlTextWriter writer, PsoArray0 arrayValue) + { + if (arrayValue.Entries != null) + { + foreach (var arrayEntry in arrayValue.Entries) + { + writer.WriteStartElement("Item"); + if (arrayEntry is PsoStructure) + { + WriteStructureContentXml((PsoStructure)arrayEntry, writer); } - else if (arrayValue.psoSection.Type == DataType.Structure) + else if (arrayEntry is PsoStructure3) { - foreach (var k in arrayValue.Entries) - { - writer.WriteStartElement("Item"); - if (k is PsoStructure) - { - WriteStructureContentXml(k as PsoStructure, writer); - } - else - { - WriteStructureElementContentXml(k, writer); - } - writer.WriteEndElement(); - } + WriteStructureContentXml((PsoStructure3)arrayEntry, writer); } else { - throw new Exception("unsupperde type"); + WriteStructureElementContentXml(arrayEntry, writer); } + writer.WriteEndElement(); } } - if (value is PsoType6) + } + + private void WriteArrayContent(XmlTextWriter writer, PsoArray1 arrayValue) + { + foreach (var arrayEntry in arrayValue.Entries) { - var v = value as PsoType6; - Write6Content(writer, v); + writer.WriteStartElement("Item"); + if (arrayEntry is PsoStructure) + { + WriteStructureContentXml((PsoStructure)arrayEntry, writer); + } + else if (arrayEntry is PsoStructure3) + { + WriteStructureContentXml((PsoStructure3)arrayEntry, writer); + } + else + { + WriteStructureElementContentXml(arrayEntry, writer); + } + writer.WriteEndElement(); } - if (value is PsoType11) + } + + private void WriteArrayContent(XmlTextWriter writer, PsoArray4 arrayValue) + { + foreach (var arrayEntry in arrayValue.Entries) { - var v = value as PsoType11; - Write11Content(writer, v); + writer.WriteStartElement("Item"); + if (arrayEntry is PsoStructure) + { + WriteStructureContentXml((PsoStructure)arrayEntry, writer); + } + else if (arrayEntry is PsoStructure3) + { + WriteStructureContentXml((PsoStructure3)arrayEntry, writer); + } + else + { + WriteStructureElementContentXml(arrayEntry, writer); + } + writer.WriteEndElement(); } - if (value is PsoType14) + } + + private void WriteBooleanContent(XmlTextWriter writer, PsoBoolean value) + { + if (value.Value) { - var v = value as PsoType14; - Write14Content(writer, v); + writer.WriteAttributeString("value", "true"); } - if (value is PsoType15) + else { - var v = value as PsoType15; - Write15Content(writer, v); + writer.WriteAttributeString("value", "false"); } - if (value is PsoStructure) + } + + private void WriteByteContent(XmlTextWriter writer, PsoByte value) + { + writer.WriteAttributeString("value", value.Value.ToString()); + } + + private void WriteEnumContent(XmlTextWriter writer, PsoEnumByte value) + { + var matchingEnumEntry = (PsoEnumEntryInfo)null; + foreach (var enumEntry in value.TypeInfo.Entries) { - var structureValue = value as PsoStructure; - WriteStructureContentXml(structureValue, writer); + if (enumEntry.EntryKey == value.Value) + matchingEnumEntry = enumEntry; + } + + if (matchingEnumEntry != null) + { + var matchingEntryName = GetNameForHash(matchingEnumEntry.EntryNameHash); + writer.WriteString(matchingEntryName); } } - private void Write6Content(XmlTextWriter writer, PsoType6 value) + private void WriteEnumContent(XmlTextWriter writer, PsoEnumInt value) { - writer.WriteAttributeString("value", value.Value.ToString()); + var matchingEnumEntry = (PsoEnumEntryInfo)null; + foreach (var enumEntry in value.TypeInfo.Entries) + { + if (enumEntry.EntryKey == value.Value) + matchingEnumEntry = enumEntry; + } + + if (matchingEnumEntry != null) + { + var matchingEntryName = GetNameForHash(matchingEnumEntry.EntryNameHash); + writer.WriteString(matchingEntryName); + } } - - private void Write11Content(XmlTextWriter writer, PsoType11 value) + + private void WriteFlagsContent(XmlTextWriter writer, PsoFlagsByte value) { - if (value.Value == null) + var sb = new StringBuilder(); + for (int i = 0; i < 8; i++) { - writer.WriteString(GetNameForHash(value.ValueHash)); + if ((value.Value & (1 << i)) != 0) + { + var machingFlagEntry = (PsoEnumEntryInfo)null; + foreach (var flagEntry in value.TypeInfo.Entries) + { + if (flagEntry.EntryKey == i) + machingFlagEntry = flagEntry; + } + + var matchingFlagName = GetNameForHash(machingFlagEntry.EntryNameHash); + sb.Append(matchingFlagName + " "); + } } - else + + var flagsString = sb.ToString().Trim(); + writer.WriteString(flagsString); + } + + private void WriteFlagsContent(XmlTextWriter writer, PsoFlagsShort value) + { + var sb = new StringBuilder(); + for (int i = 0; i < 16; i++) + { + if ((value.Value & (1 << i)) != 0) + { + var machingFlagEntry = (PsoEnumEntryInfo)null; + foreach (var flagEntry in value.TypeInfo.Entries) + { + if (flagEntry.EntryKey == i) + machingFlagEntry = flagEntry; + } + + var matchingFlagName = GetNameForHash(machingFlagEntry.EntryNameHash); + sb.Append(matchingFlagName + " "); + } + } + + var flagsString = sb.ToString().Trim(); + writer.WriteString(flagsString); + } + + private void WriteFlagsContent(XmlTextWriter writer, PsoFlagsInt value) + { + var sb = new StringBuilder(); + for (int i = 0; i < 32; i++) { - writer.WriteString(value.Value); + if ((value.Value & (1 << i)) != 0) + { + var machingFlagEntry = (PsoEnumEntryInfo)null; + foreach (var flagEntry in value.TypeInfo.Entries) + { + if (flagEntry.EntryKey == i) + machingFlagEntry = flagEntry; + } + + var matchingFlagName = GetNameForHash(machingFlagEntry.EntryNameHash); + sb.Append(matchingFlagName + " "); + } } + + var flagsString = sb.ToString().Trim(); + writer.WriteString(flagsString); } - private void Write14Content(XmlTextWriter writer, PsoType14 value) + private void WriteFloatContent(XmlTextWriter writer, PsoFloat value) { - //var sb = new StringBuilder(); - //for (int i = 0; i < 32; i++) - //{ - // if ((value.Value & (1 << i)) != 0) - // { - // sb.Append("flag_index_" + i.ToString() + " "); - // } - //} + var s1 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Value); + writer.WriteAttributeString("value", s1); + } - //writer.WriteString(sb.ToString().Trim()); + private void WriteFloatContent(XmlTextWriter writer, PsoFloat2 value) + { + var s1 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.X); + var s2 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Y); + writer.WriteAttributeString("x", s1); + writer.WriteAttributeString("y", s2); + } + + private void WriteFloatContent(XmlTextWriter writer, PsoFloat3 value) + { + var s1 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.X); + var s2 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Y); + var s3 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Z); + writer.WriteAttributeString("x", s1); + writer.WriteAttributeString("y", s2); + writer.WriteAttributeString("z", s3); + } - writer.WriteString(GetHex(value.Value)); + private void WriteFloatContent(XmlTextWriter writer, PsoFloat4A value) + { + var s1 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.X); + var s2 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Y); + var s3 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Z); + var s4 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.W); + writer.WriteAttributeString("x", s1); + writer.WriteAttributeString("y", s2); + writer.WriteAttributeString("z", s3); + writer.WriteAttributeString("w", s4); } - private void Write15Content(XmlTextWriter writer, PsoType15 value) + private void WriteFloatContent(XmlTextWriter writer, PsoFloat4B value) { - //var sb = new StringBuilder(); - //for (int i = 0; i < 32; i++) - //{ - // if ((value.Value & (1 << i)) != 0) - // { - // sb.Append("flag_index_" + i.ToString() + " "); - // } - //} + var s1 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.X); + var s2 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Y); + var s3 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.Z); + var s4 = string.Format(CultureInfo.InvariantCulture, "{0:0.0###########}", value.W); + writer.WriteAttributeString("x", s1); + writer.WriteAttributeString("y", s2); + writer.WriteAttributeString("z", s3); + writer.WriteAttributeString("w", s4); + } - //writer.WriteString(sb.ToString().Trim()); + private void WriteIntegerContent(XmlTextWriter writer, PsoIntSigned value) + { + writer.WriteAttributeString("value", value.Value.ToString()); + } - writer.WriteString(GetHex(value.Value)); + private void WriteIntegerContent(XmlTextWriter writer, PsoIntUnsigned value) + { + writer.WriteAttributeString("value", value.Value.ToString("X8")); } + private void WriteMapContent(XmlTextWriter writer, PsoMap value) + { + if (value.Entries != null) + { + foreach (var arrayEntry in value.Entries) + { + writer.WriteStartElement("Item"); + + var strKey = (PsoString7)arrayEntry.Values[0x6098a50e]; + writer.WriteAttributeString("key", GetNameForHash(strKey.Value)); + var kk = arrayEntry.Values[0x063fa3f2]; + if (kk is PsoStructure) + { + WriteStructureContentXml((PsoStructure)kk, writer); + } + else if (kk is PsoStructure3) + { + WriteStructureContentXml((PsoStructure3)kk, writer); + } + else + { + WriteStructureElementContentXml(kk, writer); + } + writer.WriteEndElement(); + } + } + } + private void WriteStringContent(XmlTextWriter writer, PsoString0 value) + { + if (value.Value != null) + { + writer.WriteString(value.Value.Replace("\0", "")); + } + } - private string GetHex(int hash) - { - return "hex_" + hash.ToString("X8"); + private void WriteStringContent(XmlTextWriter writer, PsoString1 value) + { + if (value.Value != null) + { + writer.WriteString(value.Value.Replace("\0", "")); + } } - private string GetNameForHash(int hash) + private void WriteStringContent(XmlTextWriter writer, PsoString2 value) { - if (HashMapping.ContainsKey(hash)) + if (value.Value != null) { - var ss = HashMapping[hash]; - return ss; + writer.WriteString(value.Value.Replace("\0", "")); } - return "hash_" + hash.ToString("X8"); } - private string GetEnumNameForHash(int hash) + private void WriteStringContent(XmlTextWriter writer, PsoString3 value) { - if (HashMapping.ContainsKey(hash)) + if (value.Value != null) { - var ss = HashMapping[hash]; - return ss; + writer.WriteString(value.Value.Replace("\0", "")); + } + } + + private void WriteStringContent(XmlTextWriter writer, PsoString7 value) + { + if (value.Value != 0) + { + writer.WriteString(GetNameForHash(value.Value)); } - return "enum_hash_" + hash.ToString("X8"); } - private string GetFlagNameForHash(int hash) + private void WriteStringContent(XmlTextWriter writer, PsoString8 value) + { + if (value.Value != 0) + { + writer.WriteString(GetNameForHash(value.Value)); + } + } + + + + + + + + + + private void Write5Content(XmlTextWriter writer, PsoType5 value) + { + writer.WriteAttributeString("value", value.Value.ToString()); + } + + + + + + + private string GetNameForHash(int hash) { if (HashMapping.ContainsKey(hash)) { var ss = HashMapping[hash]; return ss; } - return "flag_hash_" + hash.ToString("X8"); + else + { + throw new Exception("Hash 0x" + hash.ToString("X8") + "could not be replaced by a string."); + } } public string ByteArrayToString(byte[] b) diff --git a/RageLib.GTA5/PSOWrappers/PsoXmlImporter.cs b/RageLib.GTA5/PSOWrappers/PsoXmlImporter.cs deleted file mode 100644 index 06bdc44a..00000000 --- a/RageLib.GTA5/PSOWrappers/PsoXmlImporter.cs +++ /dev/null @@ -1,424 +0,0 @@ -/* - Copyright(c) 2016 Neodymium - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -using RageLib.GTA5.PSO; -using RageLib.GTA5.PSOWrappers.Types; -using RageLib.GTA5.PSOWrappers.Xml; -using RageLib.Hash; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Xml; - -namespace RageLib.GTA5.PSOWrappers -{ - public class PsoXmlImporter - { - private PsoDefinitionXml xmlInfos; - private List> strList; - - public PsoStructure Import(string xmlFileName) - { - using (var xmlFileStream = new FileStream(xmlFileName, FileMode.Open)) - { - return Import(xmlFileStream); - } - } - - public PsoXmlImporter(PsoDefinitionXml xmlinfos) - { - this.xmlInfos = xmlinfos; - MetaBuildStructureInfos(xmlinfos); - } - - public PsoStructure Import(Stream xmlFileStream) - { - var xmlDoc = new XmlDocument(); - xmlDoc.Load(xmlFileStream); - var rootOfData = xmlDoc.LastChild; - - var rootInfo = FindAndCheckStructure(rootOfData); - - var res = ParseStructure(rootOfData, rootInfo); - return res; - } - - public PsoStructure ParseStructure(XmlNode node, PsoStructureXml info) - { - PsoStructure resultStructure = null; - foreach (var x in strList) - if (x.Item1 == info.NameHash) - { - resultStructure = new PsoStructure(); - resultStructure.psoSection = x.Item2; - resultStructure.psoEntryInfo = new PsoElementIndexInfo(); - resultStructure.psoEntryInfo.NameHash = x.Item1; - } - - resultStructure.Values = new Dictionary(); - - foreach (var xmlEntry in info.Entries) - { - XmlNode xmlNode = null; - foreach (XmlNode x in node.ChildNodes) - { - var hash = GetHashForName(x.Name); - if (hash == xmlEntry.NameHash) - xmlNode = x; - } - - PsoStructureEntryInfo entryInfo = null; - foreach (var x in resultStructure.psoSection.Entries) - if (x.EntryNameHash == xmlEntry.NameHash) - entryInfo = x; - - var type = (DataType)xmlEntry.Type; - if (type == DataType.Array) - { - var arrayType = (DataType)xmlEntry.ArrayType.Type; - if (arrayType == DataType.Structure) - { - PsoArray arrayValue = ReadStructureArray(xmlNode, xmlEntry.ArrayType.TypeHash); - arrayValue.psoSection = resultStructure.psoSection.Entries[entryInfo.ReferenceKey]; - resultStructure.Values.Add(xmlEntry.NameHash, arrayValue); - } - else if (arrayType == DataType.INT_0Bh) - { - PsoArray arryVal = Read11Array(xmlNode); - arryVal.psoSection = resultStructure.psoSection.Entries[entryInfo.ReferenceKey]; - resultStructure.Values.Add(xmlEntry.NameHash, arryVal); - } - else if (arrayType == DataType.SHORT_0Fh) - { - PsoArray arryVal = Read14Array(xmlNode); - arryVal.psoSection = resultStructure.psoSection.Entries[entryInfo.ReferenceKey]; - resultStructure.Values.Add(xmlEntry.NameHash, arryVal); - } - else - { - throw new Exception("Unsupported array type."); - } - } - else if (type == DataType.INT_06h) - { - resultStructure.Values.Add(xmlEntry.NameHash, ReadType6(xmlNode)); - } - else if (type == DataType.INT_0Bh) - { - resultStructure.Values.Add(xmlEntry.NameHash, ReadType11(xmlNode, xmlEntry.Unknown == 0)); - } - else if (type == DataType.BYTE_ENUM_VALUE) - { - resultStructure.Values.Add(xmlEntry.NameHash, ReadType14(xmlNode)); - } - else if (type == DataType.SHORT_0Fh) - { - resultStructure.Values.Add(xmlEntry.NameHash, ReadType15(xmlNode)); - } - else if (type== DataType.Structure) - { - var xmlInfo = FindAndCheckStructure(xmlEntry.TypeHash, xmlNode); - var structureValue = ParseStructure(xmlNode, xmlInfo); - resultStructure.Values.Add(xmlEntry.NameHash, structureValue); - } - else - { - throw new Exception("Unsupported type."); - } - } - - return resultStructure; - } - - - - - - - - - - private PsoType6 ReadType6(XmlNode node) - { - PsoType6 v = new Types.PsoType6(); - v.Value = long.Parse(node.Attributes["value"].Value); - return v; - } - - private PsoType11 ReadType11(XmlNode node, bool fullString) - { - if (fullString) - { - PsoType11 v = new PsoType11(64); - v.Value = node.InnerText; - return v; - } - else - { - PsoType11 v = new PsoType11(0); - v.Value = null; - v.ValueHash = GetHashForName(node.InnerText); - return v; - } - } - - private PsoType14 ReadType14(XmlNode node) - { - PsoType14 v = new PsoType14(); - v.Value = FromHex(node.InnerText); - return v; - } - - private PsoType15 ReadType15(XmlNode node) - { - PsoType15 v = new PsoType15(); - v.Value = FromHex(node.InnerText); - return v; - } - - - - - - - - - - - private PsoArray ReadStructureArray(XmlNode node, int structureNameHash) - { - var arrayValue = new PsoArray(); - var arrayType = structureNameHash; - if (node.ChildNodes.Count > 0) - { - arrayValue.Entries = new List(); - foreach (XmlNode arrent in node.ChildNodes) - { - var xnd = FindAndCheckStructure(arrayType, arrent); - var yy = ParseStructure(arrent, xnd); - arrayValue.Entries.Add(yy); - } - } - return arrayValue; - } - - private PsoArray Read11Array(XmlNode node) - { - var arrayValue = new PsoArray(); - if (node.ChildNodes.Count > 0) - { - arrayValue.Entries = new List(); - foreach (XmlNode arrent in node.ChildNodes) - { - var y = new PsoType11(0); - y.Value = null; - y.ValueHash = GetHashForName(arrent.InnerText); - arrayValue.Entries.Add(y); - } - } - return arrayValue; - } - - private PsoArray Read14Array(XmlNode node) - { - var arrayValue = new PsoArray(); - if (node.ChildNodes.Count > 0) - { - arrayValue.Entries = new List(); - foreach (XmlNode arrent in node.ChildNodes) - { - var y = new PsoType14(); - y.Value = FromHex(arrent.Value); - arrayValue.Entries.Add(y); - } - } - return arrayValue; - } - - - - - - - - - - public int FromHex(string hashName) - { - var x = hashName.Substring(4); - int intAgain = int.Parse(x, NumberStyles.HexNumber); - return intAgain; - } - - public int GetHashForEnumName(string hashName) - { - if (hashName.StartsWith("enum_hash_", StringComparison.OrdinalIgnoreCase)) - { - var x = hashName.Substring(10); - int intAgain = int.Parse(x, NumberStyles.HexNumber); - return intAgain; - } - else - { - return (int)Jenkins.Hash(hashName); - } - } - - public int GetHashForFlagName(string hashName) - { - if (hashName.StartsWith("flag_hash_", StringComparison.OrdinalIgnoreCase)) - { - var x = hashName.Substring(10); - int intAgain = int.Parse(x, NumberStyles.HexNumber); - return intAgain; - } - else - { - return (int)Jenkins.Hash(hashName); - } - } - - public byte[] ByteFromString(string str) - { - string[] ss = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - byte[] res = new byte[ss.Length]; - for (int i = 0; i < ss.Length; i++) - { - res[i] = byte.Parse(ss[i]); - } - return res; - } - - public int GetHashForName(string hashName) - { - if (hashName.StartsWith("hash_", StringComparison.OrdinalIgnoreCase)) - { - var x = hashName.Substring(5); - int intAgain = int.Parse(x, NumberStyles.HexNumber); - return intAgain; - } - else - { - return (int)Jenkins.Hash(hashName); - } - } - - private void MetaBuildStructureInfos(PsoDefinitionXml xmlInfo) - { - //meta.DefinitionSection.EntriesIdx = new List(); - //meta.DefinitionSection.Entries = new List(); - strList = new List>(); - - foreach (var xmlStructureInfo in xmlInfo.Structures) - { - var idxInfo = new PsoElementIndexInfo(); - idxInfo.Offset = 0; - idxInfo.NameHash = xmlStructureInfo.NameHash; - - var structureInfo = new PsoStructureInfo(); - structureInfo.Type = 1; - structureInfo.Unk = (byte)xmlStructureInfo.Unknown; - structureInfo.StructureLength = xmlStructureInfo.Length; - structureInfo.Entries = new List(); - foreach (var xmlStructureEntryInfo in xmlStructureInfo.Entries) - { - var xmlArrayTypeStack = new Stack(); - var xmlArrayType = xmlStructureEntryInfo.ArrayType; - while (xmlArrayType != null) - { - xmlArrayTypeStack.Push(xmlArrayType); - xmlArrayType = xmlArrayType.ArrayType; - } - - while (xmlArrayTypeStack.Count > 0) - { - xmlArrayType = xmlArrayTypeStack.Pop(); - var arrayStructureEntryInfo = new PsoStructureEntryInfo(); - arrayStructureEntryInfo.EntryNameHash = xmlArrayType.NameHash; - arrayStructureEntryInfo.Type = (DataType)xmlArrayType.Type; - arrayStructureEntryInfo.Unk_5h = (byte)xmlArrayType.Unknown; - arrayStructureEntryInfo.DataOffset = (short)xmlArrayType.Offset; - if (arrayStructureEntryInfo.Type == DataType.Array) - { - arrayStructureEntryInfo.ReferenceKey = (short)(structureInfo.Entries.Count - 1); - } - else - { - arrayStructureEntryInfo.ReferenceKey = 0; - } - arrayStructureEntryInfo.ReferenceKey = xmlArrayType.TypeHash; - structureInfo.Entries.Add(arrayStructureEntryInfo); - } - - var structureEntryInfo = new PsoStructureEntryInfo(); - structureEntryInfo.EntryNameHash = xmlStructureEntryInfo.NameHash; - structureEntryInfo.Type = (DataType)xmlStructureEntryInfo.Type; - structureEntryInfo.Unk_5h = (byte)xmlStructureEntryInfo.Unknown; - structureEntryInfo.DataOffset = (short)xmlStructureEntryInfo.Offset; - if (structureEntryInfo.Type == DataType.Array) - { - structureEntryInfo.ReferenceKey = (short)(structureInfo.Entries.Count - 1); - } - else - { - structureEntryInfo.ReferenceKey = 0; - } - structureEntryInfo.ReferenceKey = xmlStructureEntryInfo.TypeHash; - - structureInfo.Entries.Add(structureEntryInfo); - } - - strList.Add(new Tuple(idxInfo.NameHash, structureInfo)); - - - } - } - - public PsoStructureXml FindAndCheckStructure(XmlNode node) - { - int h = GetHashForName(node.Name); - foreach (var x in xmlInfos.Structures) - { - if (x.NameHash == h) - { - return x; - } - } - - return null; - } - - public PsoStructureXml FindAndCheckStructure(int h, XmlNode node) - { - foreach (var x in xmlInfos.Structures) - { - if (x.NameHash == h) - { - return x; - } - } - - return null; - } - } -} diff --git a/RageLib.GTA5/PSOWrappers/Types/IPsoValue.cs b/RageLib.GTA5/PSOWrappers/Types/IPsoValue.cs index 4701a625..476f2e97 100644 --- a/RageLib.GTA5/PSOWrappers/Types/IPsoValue.cs +++ b/RageLib.GTA5/PSOWrappers/Types/IPsoValue.cs @@ -21,12 +21,13 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { public interface IPsoValue { - void Read(DataReader reader); + void Read(PsoDataReader reader); void Write(DataWriter writer); } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoArray0.cs b/RageLib.GTA5/PSOWrappers/Types/PsoArray0.cs new file mode 100644 index 00000000..c9649183 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoArray0.cs @@ -0,0 +1,104 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; +using System; +using System.Collections.Generic; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoArray0 : IPsoValue + { + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoStructureEntryInfo entryInfo; + public List Entries { get; set; } + + public PsoArray0(PsoFile pso, PsoStructureInfo structureInfo, PsoStructureEntryInfo entryInfo) + { + this.pso = pso; + this.structureInfo = structureInfo; + this.entryInfo = entryInfo; + } + + public void Read(PsoDataReader reader) + { + var blockIndexAndOffset = reader.ReadUInt32(); + var BlockIndex = (int)(blockIndexAndOffset & 0x00000FFF); + var Offset = (int)((blockIndexAndOffset & 0xFFFFF000) >> 12); + var zero_4h = reader.ReadUInt32(); + if (zero_4h != 0) + { + throw new Exception("zero_4h should be 0"); + } + var size1 = reader.ReadUInt16(); + var size2 = reader.ReadUInt16(); + if (size1 != size2) + { + throw new Exception("size1 should be size2"); + } + var NumberOfEntries = size1; + var zero_Ch = reader.ReadUInt32(); + if (zero_Ch != 0) + { + throw new Exception("zero_Ch should be 0"); + } + + if (BlockIndex > 0) + { + // read reference data... + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(BlockIndex - 1); + reader.Position = Offset; + + Entries = new List(); + for (int i = 0; i < NumberOfEntries; i++) + { + var entry = PsoTypeBuilder.Make(pso, structureInfo, entryInfo); + entry.Read(reader); + Entries.Add(entry); + } + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + } + else + { + Entries = null; + } + } + + public void Write(DataWriter writer) + { + //uint blockIndexAndOffset = (uint)BlockIndex | ((uint)Offset << 12); + //writer.Write(blockIndexAndOffset); + //writer.Write((uint)0); + //writer.Write((ushort)NumberOfEntries); + //writer.Write((ushort)NumberOfEntries); + //writer.Write((uint)0); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoArray1.cs b/RageLib.GTA5/PSOWrappers/Types/PsoArray1.cs new file mode 100644 index 00000000..593620cc --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoArray1.cs @@ -0,0 +1,62 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; +using System.Collections.Generic; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoArray1 : IPsoValue + { + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoStructureEntryInfo entryInfo; + public readonly int numberOfEntries; + public List Entries { get; set; } + + public PsoArray1(PsoFile pso, PsoStructureInfo structureInfo, PsoStructureEntryInfo entryInfo, int numberOfEntries) + { + this.pso = pso; + this.structureInfo = structureInfo; + this.entryInfo = entryInfo; + this.numberOfEntries = numberOfEntries; + } + + public void Read(PsoDataReader reader) + { + Entries = new List(); + for (int i = 0; i < numberOfEntries; i++) + { + var entry = PsoTypeBuilder.Make(pso, structureInfo, entryInfo); + entry.Read(reader); + Entries.Add(entry); + } + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoArray4.cs b/RageLib.GTA5/PSOWrappers/Types/PsoArray4.cs new file mode 100644 index 00000000..e79c60e7 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoArray4.cs @@ -0,0 +1,62 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; +using System.Collections.Generic; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoArray4 : IPsoValue + { + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoStructureEntryInfo entryInfo; + public readonly int numberOfEntries; + public List Entries { get; set; } + + public PsoArray4(PsoFile pso, PsoStructureInfo structureInfo, PsoStructureEntryInfo entryInfo, int numberOfEntries) + { + this.pso = pso; + this.structureInfo = structureInfo; + this.entryInfo = entryInfo; + this.numberOfEntries = numberOfEntries; + } + + public void Read(PsoDataReader reader) + { + Entries = new List(); + for (int i = 0; i < numberOfEntries; i++) + { + var entry = PsoTypeBuilder.Make(pso, structureInfo, entryInfo); + entry.Read(reader); + Entries.Add(entry); + } + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType21.cs b/RageLib.GTA5/PSOWrappers/Types/PsoBoolean.cs similarity index 86% rename from RageLib.GTA5/PSOWrappers/Types/PsoType21.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoBoolean.cs index 9d0cc15b..a9b9234f 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType21.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoBoolean.cs @@ -21,19 +21,21 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType21 : IPsoValue + public class PsoBoolean : IPsoValue { - public void Read(DataReader reader) + public bool Value { get; set; } + + public void Read(PsoDataReader reader) { - var x1 = reader.ReadInt32(); + Value = reader.ReadByte() != 0; } public void Write(DataWriter writer) { - } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType2.cs b/RageLib.GTA5/PSOWrappers/Types/PsoByte.cs similarity index 86% rename from RageLib.GTA5/PSOWrappers/Types/PsoType2.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoByte.cs index f4e8305c..1f11272f 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType2.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoByte.cs @@ -21,14 +21,17 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType2 : IPsoValue + public class PsoByte : IPsoValue { - public void Read(DataReader reader) + public byte Value { get; set; } + + public void Read(PsoDataReader reader) { - var x1 = reader.ReadInt32(); + Value = reader.ReadByte(); } public void Write(DataWriter writer) diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoEnumByte.cs b/RageLib.GTA5/PSOWrappers/Types/PsoEnumByte.cs new file mode 100644 index 00000000..d1bf5ebe --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoEnumByte.cs @@ -0,0 +1,58 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoEnumByte : IPsoValue + { + public PsoEnumInfo TypeInfo { get; set; } + public byte Value { get; set; } + + public PsoEnumByte() + { } + + public PsoEnumByte(byte value) + { + this.Value = value; + } + + public PsoEnumByte(PsoEnumInfo typeInfo, byte value) + { + this.TypeInfo = typeInfo; + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + Value = reader.ReadByte(); + } + + public void Write(DataWriter writer) + { + writer.Write(this.Value); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoEnumInt.cs b/RageLib.GTA5/PSOWrappers/Types/PsoEnumInt.cs new file mode 100644 index 00000000..8e1231a2 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoEnumInt.cs @@ -0,0 +1,58 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoEnumInt : IPsoValue + { + public PsoEnumInfo TypeInfo { get; set; } + public int Value { get; set; } + + public PsoEnumInt() + { } + + public PsoEnumInt(int value) + { + this.Value = value; + } + + public PsoEnumInt(PsoEnumInfo typeInfo, int value) + { + this.TypeInfo = typeInfo; + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + Value = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write(this.Value); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFlagsByte.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsByte.cs new file mode 100644 index 00000000..62940193 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsByte.cs @@ -0,0 +1,58 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFlagsByte : IPsoValue + { + public PsoEnumInfo TypeInfo; + public byte Value { get; set; } + + public PsoFlagsByte() + { } + + public PsoFlagsByte(byte value) + { + this.Value = value; + } + + public PsoFlagsByte(PsoEnumInfo typeInfo, byte value) + { + this.TypeInfo = typeInfo; + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + this.Value = reader.ReadByte(); + } + + public void Write(DataWriter writer) + { + writer.Write(this.Value); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFlagsInt.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsInt.cs new file mode 100644 index 00000000..84fcd181 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsInt.cs @@ -0,0 +1,58 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFlagsInt : IPsoValue + { + public PsoEnumInfo TypeInfo; + public int Value { get; set; } + + public PsoFlagsInt() + { } + + public PsoFlagsInt(byte value) + { + this.Value = value; + } + + public PsoFlagsInt(PsoEnumInfo typeInfo, byte value) + { + this.TypeInfo = typeInfo; + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + this.Value = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + writer.Write(this.Value); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFlagsShort.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsShort.cs new file mode 100644 index 00000000..c1847517 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFlagsShort.cs @@ -0,0 +1,58 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFlagsShort : IPsoValue + { + public PsoEnumInfo TypeInfo; + public short Value { get; set; } + + public PsoFlagsShort() + { } + + public PsoFlagsShort(byte value) + { + this.Value = value; + } + + public PsoFlagsShort(PsoEnumInfo typeInfo, byte value) + { + this.TypeInfo = typeInfo; + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + this.Value = reader.ReadInt16(); + } + + public void Write(DataWriter writer) + { + writer.Write(this.Value); + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFloat.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFloat.cs index 53b278b3..ecc13730 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoFloat.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFloat.cs @@ -21,13 +21,17 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { public class PsoFloat : IPsoValue { - public void Read(DataReader reader) + public float Value { get; set; } + + public void Read(PsoDataReader reader) { + Value = reader.ReadSingle(); } public void Write(DataWriter writer) diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFloat2.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFloat2.cs new file mode 100644 index 00000000..21a4483e --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFloat2.cs @@ -0,0 +1,47 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFloat2 : IPsoValue + { + public float X { get; set; } + public float Y { get; set; } + + public PsoFloat2() + { } + + public void Read(PsoDataReader reader) + { + this.X = reader.ReadSingle(); + this.Y = reader.ReadSingle(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFloat3.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFloat3.cs new file mode 100644 index 00000000..d70c463c --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFloat3.cs @@ -0,0 +1,49 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFloat3 : IPsoValue + { + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + + public PsoFloat3() + { } + + public void Read(PsoDataReader reader) + { + X = reader.ReadSingle(); + Y = reader.ReadSingle(); + Z = reader.ReadSingle(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFloat4A.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFloat4A.cs new file mode 100644 index 00000000..e74c78e0 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFloat4A.cs @@ -0,0 +1,48 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFloat4A : IPsoValue + { + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + public float W { get; set; } + + public void Read(PsoDataReader reader) + { + X = reader.ReadSingle(); + Y = reader.ReadSingle(); + Z = reader.ReadSingle(); + W = reader.ReadSingle(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoFloat4B.cs b/RageLib.GTA5/PSOWrappers/Types/PsoFloat4B.cs new file mode 100644 index 00000000..813652ba --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoFloat4B.cs @@ -0,0 +1,51 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoFloat4B : IPsoValue + { + public float X { get; set; } + public float Y { get; set; } + public float Z { get; set; } + public float W { get; set; } + + public PsoFloat4B() + { } + + public void Read(PsoDataReader reader) + { + this.X = reader.ReadSingle(); + this.Y = reader.ReadSingle(); + this.Z = reader.ReadSingle(); + this.W = reader.ReadSingle(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType15.cs b/RageLib.GTA5/PSOWrappers/Types/PsoIntSigned.cs similarity index 87% rename from RageLib.GTA5/PSOWrappers/Types/PsoType15.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoIntSigned.cs index 36b83b02..c7288e01 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType15.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoIntSigned.cs @@ -21,22 +21,18 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType15 : IPsoValue + public class PsoIntSigned : IPsoValue { public int Value { get; set; } - public PsoType15() + public PsoIntSigned() { } - public PsoType15(int value) - { - this.Value = value; - } - - public void Read(DataReader reader) + public void Read(PsoDataReader reader) { this.Value = reader.ReadInt32(); } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType6.cs b/RageLib.GTA5/PSOWrappers/Types/PsoIntUnsigned.cs similarity index 81% rename from RageLib.GTA5/PSOWrappers/Types/PsoType6.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoIntUnsigned.cs index 85065a0d..74f43c8c 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType6.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoIntUnsigned.cs @@ -21,25 +21,20 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - // length=8 (max) - public class PsoType6 : IPsoValue + public class PsoIntUnsigned : IPsoValue { - public long Value { get; set; } + public uint Value { get; set; } - public PsoType6() + public PsoIntUnsigned() { } - public PsoType6(long value) + public void Read(PsoDataReader reader) { - this.Value = value; - } - - public void Read(DataReader reader) - { - this.Value = reader.ReadInt64(); + this.Value = reader.ReadUInt32(); } public void Write(DataWriter writer) diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoMap.cs b/RageLib.GTA5/PSOWrappers/Types/PsoMap.cs new file mode 100644 index 00000000..197d965f --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoMap.cs @@ -0,0 +1,108 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; +using System; +using System.Collections.Generic; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoMap : IPsoValue + { + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoStructureEntryInfo keyEntryInfo; + public readonly PsoStructureEntryInfo valueEntryInfo; + public List Entries { get; set; } + + public PsoMap( + PsoFile pso, + PsoStructureInfo structureInfo, + PsoStructureEntryInfo keyEntryInfo, + PsoStructureEntryInfo valueEntryInfo) + { + this.pso = pso; + this.structureInfo = structureInfo; + this.keyEntryInfo = keyEntryInfo; + this.valueEntryInfo = valueEntryInfo; + } + + public void Read(PsoDataReader reader) + { + int x1 = reader.ReadInt32(); + int x2 = reader.ReadInt32(); + int x3 = reader.ReadInt32(); + int unk = (x3 >> 12) & 0x000FFFFF; + int sectionIndex = x3 & 0x00000FFF; + + int x4 = reader.ReadInt32(); + + + int x5 = reader.ReadInt32(); + int length1 = (x5 >> 16) & 0x0000FFFF; + int length2 = x5 & 0x0000FFFF; + if (length1 != length2) + throw new Exception("length does not match"); + + int x6 = reader.ReadInt32(); + + + + + // read reference data... + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(sectionIndex - 1); + reader.Position = unk; + + int nameOfDataSection = pso.DataMappingSection.Entries[sectionIndex - 1].NameHash; + var sectionInfo = (PsoStructureInfo)null; + //var sectionIdxInfo = (PsoElementIndexInfo)null; + for (int k = 0; k < pso.DefinitionSection.EntriesIdx.Count; k++) + { + if (pso.DefinitionSection.EntriesIdx[k].NameHash == nameOfDataSection) + { + sectionInfo = (PsoStructureInfo)pso.DefinitionSection.Entries[k]; + //sectionIdxInfo = pso.DefinitionSection.EntriesIdx[k]; + } + } + + Entries = new List(); + for (int i = 0; i < length1; i++) + { + var entryStr = new PsoStructure(pso, sectionInfo, null, null); + entryStr.Read(reader); + Entries.Add(entryStr); + } + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + } + + public void Write(DataWriter writer) + { + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoString0.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString0.cs new file mode 100644 index 00000000..0227f815 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString0.cs @@ -0,0 +1,64 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; +using System; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoString0 : IPsoValue + { + private readonly int length; + public string Value { get; set; } + + public PsoString0(int length) + { + this.length = length; + } + + public void Read(PsoDataReader reader) + { + Value = ""; + bool isok = true; + for (int i = 0; i < length; i++) + { + char c = (char)reader.ReadByte(); + if (c == 0) + { + isok = false; + } + else + { + if (!isok) + throw new Exception("Unexpected char."); + Value += c; + } + } + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoString1.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString1.cs new file mode 100644 index 00000000..01b891e0 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString1.cs @@ -0,0 +1,63 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; +using System; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoString1 : IPsoValue + { + public string Value { get; set; } + + public void Read(PsoDataReader reader) + { + int x1 = reader.ReadInt32(); + int x2 = reader.ReadInt32(); + if (x2 != 0) + { + throw new Exception("zero_Ch should be 0"); + } + + var BlockIndex = (int)(x1 & 0x00000FFF); + var Offset = (int)((x1 & 0xFFFFF000) >> 12); + + // read reference data... + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(BlockIndex - 1); + reader.Position = Offset; + + Value = reader.ReadString(); + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoString2.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString2.cs new file mode 100644 index 00000000..e927f9e4 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString2.cs @@ -0,0 +1,63 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; +using System; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoString2 : IPsoValue + { + public string Value { get; set; } + + public void Read(PsoDataReader reader) + { + int x1 = reader.ReadInt32(); + int x2 = reader.ReadInt32(); + if (x2 != 0) + { + throw new Exception("zero_Ch should be 0"); + } + + var BlockIndex = (int)(x1 & 0x00000FFF); + var Offset = (int)((x1 & 0xFFFFF000) >> 12); + + // read reference data... + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(BlockIndex - 1); + reader.Position = Offset; + + Value = reader.ReadString(); + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoArray.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString3.cs similarity index 57% rename from RageLib.GTA5/PSOWrappers/Types/PsoArray.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoString3.cs index 467217ff..c0355c7f 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoArray.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString3.cs @@ -21,55 +21,71 @@ THE SOFTWARE. */ using RageLib.Data; -using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; using System; -using System.Collections.Generic; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoArray : IPsoValue + public class PsoString3 : IPsoValue { - public PsoStructureEntryInfo psoSection; + public string Value { get; set; } - public int BlockIndex { get; set; } - public int Offset { get; set; } - public int NumberOfEntries { get; set; } - - // Reference values - public List Entries { get; set; } - - public void Read(DataReader reader) + public void Read(PsoDataReader reader) { var blockIndexAndOffset = reader.ReadUInt32(); - this.BlockIndex = (int)(blockIndexAndOffset & 0x00000FFF); - this.Offset = (int)((blockIndexAndOffset & 0xFFFFF000) >> 12); + var BlockIndex = (int)(blockIndexAndOffset & 0x00000FFF); + var Offset = (int)((blockIndexAndOffset & 0xFFFFF000) >> 12); var zero_4h = reader.ReadUInt32(); if (zero_4h != 0) { throw new Exception("zero_4h should be 0"); } - var size1 = reader.ReadUInt16(); - var size2 = reader.ReadUInt16(); - if (size1 != size2) - { - throw new Exception("size1 should be size2"); - } - this.NumberOfEntries = size1; + var size1 = reader.ReadUInt16() & 0x0FFF; + var size2 = reader.ReadUInt16() & 0x0FFF; + //if (size1 != size2 - 1) + //{ + // throw new Exception("size1 should be size2"); + //} + var NumberOfEntries = size2; var zero_Ch = reader.ReadUInt32(); if (zero_Ch != 0) { throw new Exception("zero_Ch should be 0"); } + + + // read reference data... + if (BlockIndex > 0) + { + + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(BlockIndex - 1); + reader.Position = Offset; + + string s = ""; + for (int k = 0; k < NumberOfEntries; k++) + { + s += (char)reader.ReadByte(); + } + Value = s; + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + + + + } + else + { + Value = null; + } } public void Write(DataWriter writer) { - uint blockIndexAndOffset = (uint)BlockIndex | ((uint)Offset << 12); - writer.Write(blockIndexAndOffset); - writer.Write((uint)0); - writer.Write((ushort)NumberOfEntries); - writer.Write((ushort)NumberOfEntries); - writer.Write((uint)0); + } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType14.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString7.cs similarity index 84% rename from RageLib.GTA5/PSOWrappers/Types/PsoType14.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoString7.cs index e345796a..1396d2dd 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType14.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString7.cs @@ -21,29 +21,31 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; +using System; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType14 : IPsoValue + public class PsoString7 : IPsoValue { public int Value { get; set; } - public PsoType14() + public PsoString7() { } - public PsoType14(int value) + public PsoString7(int value) { this.Value = value; } - public void Read(DataReader reader) + public void Read(PsoDataReader reader) { - this.Value = reader.ReadInt32(); + Value = reader.ReadInt32(); } public void Write(DataWriter writer) { - writer.Write(this.Value); + } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoString8.cs b/RageLib.GTA5/PSOWrappers/Types/PsoString8.cs new file mode 100644 index 00000000..2c05e61a --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoString8.cs @@ -0,0 +1,53 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoString8 : IPsoValue + { + public int Value { get; set; } + + public PsoString8() + { } + + public PsoString8(int value) + { + this.Value = value; + } + + public void Read(PsoDataReader reader) + { + int z1 = reader.ReadInt32(); + int z2 = reader.ReadInt32(); + + Value = z1; + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoStructure.cs b/RageLib.GTA5/PSOWrappers/Types/PsoStructure.cs index f98c6b0b..48bdb2e5 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoStructure.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoStructure.cs @@ -22,174 +22,67 @@ THE SOFTWARE. using RageLib.Data; using RageLib.GTA5.PSO; -using System; +using RageLib.GTA5.PSOWrappers.Data; using System.Collections.Generic; namespace RageLib.GTA5.PSOWrappers.Types { public class PsoStructure : IPsoValue { - public PsoFile pso; - public PsoElementIndexInfo psoEntryInfo; - public PsoStructureInfo psoSection; + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoElementIndexInfo entryIndexInfo; + public readonly PsoStructureEntryInfo entryInfo; public Dictionary Values { get; set; } - public void Read(DataReader reader) + public PsoStructure(PsoFile pso, PsoStructureInfo structureInfo, PsoElementIndexInfo entryIndexInfo, PsoStructureEntryInfo entryInfo) { - long position = reader.Position; + this.pso = pso; + this.structureInfo = structureInfo; + this.entryIndexInfo = entryIndexInfo; + this.entryInfo = entryInfo; + this.Values = new Dictionary(); + } + + public void Read(PsoDataReader reader) + { + long backupOfPosition = reader.Position; this.Values = new Dictionary(); - for (int i = 0; i < psoSection.Entries.Count; i++) + for (int i = 0; i < structureInfo.Entries.Count; i++) { - var x1 = psoSection.Entries[i]; + // skip unnamed entries... + var x1 = structureInfo.Entries[i]; if (x1.EntryNameHash == 0x100) continue; - reader.Position = position + x1.DataOffset; - switch (x1.Type) - { - case DataType.Array: - { - var entryValue = new PsoArray(); - entryValue.psoSection = psoSection.Entries[x1.ReferenceKey & 0x0000FFFF]; - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.INT_0Bh: - { - if (psoSection.Entries[i].ReferenceKey == 0) - { - var entryValue = new PsoType11(0); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - } - else - { - var entryValue = new PsoType11(64); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - } - - break; - } - case DataType.BYTE_ENUM_VALUE: - { - var entryValue = new PsoType14(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.SHORT_0Fh: - { - var entryValue = new PsoType15(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.INT_06h: - { - var entryValue = new PsoType6(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.Structure: - { - var entryValue = new PsoStructure(); - entryValue.pso = pso; - entryValue.psoSection = GetStructureInfo(pso, x1.ReferenceKey); - entryValue.psoEntryInfo = GetStructureIndexInfo(pso, x1.ReferenceKey); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - - case DataType.TYPE_10h: - { - var entryValue = new PsoType16(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.INT_05h: - { - var entryValue = new PsoType5(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.BYTE_02h: - { - var entryValue = new PsoType2(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.Float: - { - var entryValue = new PsoFloat(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.BYTE_00h: - { - var entryValue = new PsoType0(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - case DataType.TYPE_15h: - { - var entryValue = new PsoType21(); - entryValue.Read(reader); - this.Values.Add(x1.EntryNameHash, entryValue); - break; - } - default: - throw new Exception("Unknown Type"); - } + reader.Position = backupOfPosition + x1.DataOffset; + var value = PsoTypeBuilder.Make(pso, structureInfo, x1); + value.Read(reader); + Values.Add(x1.EntryNameHash, value); } - reader.Position = position + psoSection.StructureLength; - } - - public void Write(DataWriter writer) - { - long position = writer.Position; - - writer.Write(new byte[psoSection.StructureLength]); - writer.Position = position; - - foreach (var entry in psoSection.Entries) - { - if (entry.EntryNameHash != 0x100) - { - writer.Position = position + entry.DataOffset; - this.Values[entry.EntryNameHash].Write(writer); - } - } - writer.Position = position + psoSection.StructureLength; - } + reader.Position = backupOfPosition + structureInfo.StructureLength; - public static PsoStructureInfo GetStructureInfo(PsoFile meta, int structureKey) - { - PsoStructureInfo info = null; - for (int i = 0; i < meta.DefinitionSection.Count; i++) - if (meta.DefinitionSection.EntriesIdx[i].NameHash == structureKey) - info = (PsoStructureInfo)meta.DefinitionSection.Entries[i]; - return info; } - public static PsoElementIndexInfo GetStructureIndexInfo(PsoFile meta, int structureKey) + public void Write(DataWriter writer) { - PsoElementIndexInfo info = null; - for (int i = 0; i < meta.DefinitionSection.Count; i++) - if (meta.DefinitionSection.EntriesIdx[i].NameHash == structureKey) - info = (PsoElementIndexInfo)meta.DefinitionSection.EntriesIdx[i]; - return info; + //long position = writer.Position; + + //writer.Write(new byte[psoSection.StructureLength]); + //writer.Position = position; + + //foreach (var entry in psoSection.Entries) + //{ + // if (entry.EntryNameHash != 0x100) + // { + // writer.Position = position + entry.DataOffset; + // this.Values[entry.EntryNameHash].Write(writer); + // } + //} + //writer.Position = position + psoSection.StructureLength; } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoStructure3.cs b/RageLib.GTA5/PSOWrappers/Types/PsoStructure3.cs new file mode 100644 index 00000000..24b4e65d --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoStructure3.cs @@ -0,0 +1,93 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSO; +using RageLib.GTA5.PSOWrappers.Data; +using System; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoStructure3 : IPsoValue + { + public readonly PsoFile pso; + public readonly PsoStructureInfo structureInfo; + public readonly PsoStructureEntryInfo entryInfo; + public PsoStructure Value { get; set; } + + public PsoStructure3(PsoFile pso, PsoStructureInfo structureInfo, PsoStructureEntryInfo entryInfo) + { + this.pso = pso; + this.structureInfo = structureInfo; + this.entryInfo = entryInfo; + } + + public void Read(PsoDataReader reader) + { + int z1 = reader.ReadInt32(); + int z2 = reader.ReadInt32(); + if (z2 != 0) + throw new Exception("z2 should be zero"); + + int offset = (z1 >> 12) & 0x000FFFFF; + int sectionIndex = z1 & 0x00000FFF; + + if (sectionIndex > 0) + { + var nameHash = pso.DataMappingSection.Entries[sectionIndex - 1].NameHash; + var strInfo = (PsoStructureInfo)null; + var sectionIdxInfo = (PsoElementIndexInfo)null; + for (int k = 0; k < pso.DefinitionSection.Entries.Count; k++) + { + if (pso.DefinitionSection.EntriesIdx[k].NameHash == nameHash) + { + strInfo = (PsoStructureInfo)pso.DefinitionSection.Entries[k]; + sectionIdxInfo = pso.DefinitionSection.EntriesIdx[k]; + } + } + + + // read reference data... + var backupOfSection = reader.CurrentSectionIndex; + var backupOfPosition = reader.Position; + + reader.SetSectionIndex(sectionIndex - 1); + reader.Position = offset; + + Value = new PsoStructure(pso, strInfo, sectionIdxInfo, null); + Value.Read(reader); + + reader.SetSectionIndex(backupOfSection); + reader.Position = backupOfPosition; + } + else + { + Value = null; + } + + } + + public void Write(DataWriter writer) + { + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType11.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType11.cs deleted file mode 100644 index e75ba8c3..00000000 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType11.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright(c) 2016 Neodymium - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -using RageLib.Data; -using System; -using System.Text; - -namespace RageLib.GTA5.PSOWrappers.Types -{ - public class PsoType11 : IPsoValue - { - private readonly int length; - - public int ValueHash { get; set; } - public string Value { get; set; } - - public PsoType11(int length) - { - this.length = length; - } - - public PsoType11(int length, string value) - { - this.length = length; - this.Value = value; - } - - public void Read(DataReader reader) - { - if (length == 0) - { - this.ValueHash = reader.ReadInt32(); - } - else - { - var valueBuilder = new StringBuilder(); - var valueValid = true; - for (int i = 0; i < length; i++) - { - char c = (char)reader.ReadByte(); - if (c == 0) - { - valueValid = false; - } - if (valueValid) - { - valueBuilder.Append((char)c); - } - else - { - if (c != 0) - { - throw new Exception("c should be 0"); - } - } - } - this.Value = valueBuilder.ToString(); - } - } - - public void Write(DataWriter writer) - { - if (length == 0) - { - writer.Write(ValueHash); - } - else - { - for (int i = 0; i < Value.Length; i++) - { - writer.Write((byte)Value[i]); - } - for (int i = Value.Length; i < 64; i++) - { - writer.Write((byte)0); - } - } - } - } -} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType16.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType3.cs similarity index 84% rename from RageLib.GTA5/PSOWrappers/Types/PsoType16.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoType3.cs index 2df49a1f..8e1a1f12 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType16.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoType3.cs @@ -21,20 +21,25 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType16 : IPsoValue + public class PsoType3 : IPsoValue { - public PsoType16() + public short Value { get; set; } + + public PsoType3() { } - public void Read(DataReader reader) + public void Read(PsoDataReader reader) { + Value = reader.ReadInt16(); } public void Write(DataWriter writer) { + } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType32.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType32.cs new file mode 100644 index 00000000..86dfd10a --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoType32.cs @@ -0,0 +1,46 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoType32 : IPsoValue + { + public int Value { get; set; } + + public PsoType32() + { } + + public void Read(PsoDataReader reader) + { + int z1 = reader.ReadInt32(); + int z2 = reader.ReadInt32(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType0.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType4.cs similarity index 84% rename from RageLib.GTA5/PSOWrappers/Types/PsoType0.cs rename to RageLib.GTA5/PSOWrappers/Types/PsoType4.cs index 19cc1983..3609f689 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType0.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoType4.cs @@ -21,17 +21,25 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { - public class PsoType0 : IPsoValue + public class PsoType4 : IPsoValue { - public void Read(DataReader reader) + public short Value { get; set; } + + public PsoType4() + { } + + public void Read(PsoDataReader reader) { + Value = reader.ReadInt16(); } public void Write(DataWriter writer) { + } } } diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType5.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType5.cs index 8a5106d5..06019558 100644 --- a/RageLib.GTA5/PSOWrappers/Types/PsoType5.cs +++ b/RageLib.GTA5/PSOWrappers/Types/PsoType5.cs @@ -21,17 +21,20 @@ THE SOFTWARE. */ using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; namespace RageLib.GTA5.PSOWrappers.Types { public class PsoType5 : IPsoValue { + public int Value { get; set; } + public PsoType5() { } - public void Read(DataReader reader) + public void Read(PsoDataReader reader) { - var x1 = reader.ReadInt32(); + Value = reader.ReadInt32(); } public void Write(DataWriter writer) diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoType9.cs b/RageLib.GTA5/PSOWrappers/Types/PsoType9.cs new file mode 100644 index 00000000..35338bc8 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoType9.cs @@ -0,0 +1,48 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoType9 : IPsoValue + { + public int Value { get; set; } + + public PsoType9() + { } + + public void Read(PsoDataReader reader) + { + var x1 = reader.ReadSingle(); + var x2 = reader.ReadSingle(); + var x3 = reader.ReadSingle(); + var x4 = reader.ReadSingle(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoXXByte.cs b/RageLib.GTA5/PSOWrappers/Types/PsoXXByte.cs new file mode 100644 index 00000000..587d24b7 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoXXByte.cs @@ -0,0 +1,45 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoXXByte : IPsoValue + { + public byte Value { get; set; } + + public PsoXXByte() + { } + + public void Read(PsoDataReader reader) + { + Value = reader.ReadByte(); + } + + public void Write(DataWriter writer) + { + + } + } +} diff --git a/RageLib.GTA5/PSOWrappers/Types/PsoXXHalf.cs b/RageLib.GTA5/PSOWrappers/Types/PsoXXHalf.cs new file mode 100644 index 00000000..c53c1522 --- /dev/null +++ b/RageLib.GTA5/PSOWrappers/Types/PsoXXHalf.cs @@ -0,0 +1,45 @@ +/* + Copyright(c) 2016 Neodymium + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +using RageLib.Data; +using RageLib.GTA5.PSOWrappers.Data; + +namespace RageLib.GTA5.PSOWrappers.Types +{ + public class PsoXXHalf : IPsoValue + { + public short Value { get; set; } + + public PsoXXHalf() + { } + + public void Read(PsoDataReader reader) + { + Value = reader.ReadInt16(); + } + + public void Write(DataWriter writer) + { + writer.Write(Value); + } + } +} diff --git a/RageLib.GTA5/RageLib.GTA5.csproj b/RageLib.GTA5/RageLib.GTA5.csproj index b2ab69af..6cc3393b 100755 --- a/RageLib.GTA5/RageLib.GTA5.csproj +++ b/RageLib.GTA5/RageLib.GTA5.csproj @@ -51,7 +51,50 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62,28 +105,6 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -346,14 +367,12 @@ + - - - - + - +