diff --git a/SabreTools.Serialization/Deserializers/BFPK.cs b/SabreTools.Serialization/Deserializers/BFPK.cs index 05f0d790..a9828d43 100644 --- a/SabreTools.Serialization/Deserializers/BFPK.cs +++ b/SabreTools.Serialization/Deserializers/BFPK.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.BFPK; -using static SabreTools.Models.BFPK.Constants; +using SabreTools.Serialization.Models.BFPK; +using static SabreTools.Serialization.Models.BFPK.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/BSP.cs b/SabreTools.Serialization/Deserializers/BSP.cs index 894f62f4..76eb807f 100644 --- a/SabreTools.Serialization/Deserializers/BSP.cs +++ b/SabreTools.Serialization/Deserializers/BSP.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.BSP; -using static SabreTools.Models.BSP.Constants; +using SabreTools.Serialization.Models.BSP; +using static SabreTools.Serialization.Models.BSP.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/GCF.cs b/SabreTools.Serialization/Deserializers/GCF.cs index 3a426565..81350210 100644 --- a/SabreTools.Serialization/Deserializers/GCF.cs +++ b/SabreTools.Serialization/Deserializers/GCF.cs @@ -1,14 +1,14 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.GCF; +using SabreTools.Serialization.Models.GCF; namespace SabreTools.Serialization.Deserializers { - public class GCF : BaseBinaryDeserializer + public class GCF : BaseBinaryDeserializer { /// - public override SabreTools.Models.GCF.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.GCF.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -20,7 +20,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new Half-Life Game Cache to fill - var file = new SabreTools.Models.GCF.File(); + var file = new SabreTools.Serialization.Models.GCF.File(); #region Header @@ -113,7 +113,7 @@ namespace SabreTools.Serialization.Deserializers return null; if (directoryHeader.Dummy1 != 0x00008000) return null; - + // Set the game cache directory header file.DirectoryHeader = directoryHeader; diff --git a/SabreTools.Serialization/Deserializers/GZip.cs b/SabreTools.Serialization/Deserializers/GZip.cs index ff793b02..a7172bf4 100644 --- a/SabreTools.Serialization/Deserializers/GZip.cs +++ b/SabreTools.Serialization/Deserializers/GZip.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.GZIP; -using static SabreTools.Models.GZIP.Constants; +using SabreTools.Serialization.Models.GZIP; +using static SabreTools.Serialization.Models.GZIP.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs index 9fd8db03..e7bb0648 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldArchiveV3.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.InstallShieldArchiveV3; +using SabreTools.Serialization.Models.InstallShieldArchiveV3; namespace SabreTools.Serialization.Deserializers { @@ -47,7 +47,7 @@ namespace SabreTools.Serialization.Deserializers data.Seek(directoriesOffset, SeekOrigin.Begin); // Try to parse the directories - var directories = new List(); + var directories = new List(); for (int i = 0; i < header.DirCount; i++) { var directory = ParseDirectory(data); @@ -63,7 +63,7 @@ namespace SabreTools.Serialization.Deserializers #region Files // Try to parse the files - var files = new List(); + var files = new List(); for (int i = 0; i < archive.Directories.Length; i++) { var directory = archive.Directories[i]; @@ -94,9 +94,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled Directory on success, null on error - public static SabreTools.Models.InstallShieldArchiveV3.Directory ParseDirectory(Stream data) + public static SabreTools.Serialization.Models.InstallShieldArchiveV3.Directory ParseDirectory(Stream data) { - var obj = new SabreTools.Models.InstallShieldArchiveV3.Directory(); + var obj = new SabreTools.Serialization.Models.InstallShieldArchiveV3.Directory(); obj.FileCount = data.ReadUInt16LittleEndian(); obj.ChunkSize = data.ReadUInt16LittleEndian(); @@ -113,9 +113,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled File on success, null on error - public static SabreTools.Models.InstallShieldArchiveV3.File ParseFile(Stream data) + public static SabreTools.Serialization.Models.InstallShieldArchiveV3.File ParseFile(Stream data) { - var obj = new SabreTools.Models.InstallShieldArchiveV3.File(); + var obj = new SabreTools.Serialization.Models.InstallShieldArchiveV3.File(); obj.VolumeEnd = data.ReadByteValue(); obj.Index = data.ReadUInt16LittleEndian(); diff --git a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs index 43ca313f..0b892b49 100644 --- a/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Deserializers/InstallShieldCabinet.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.InstallShieldCabinet; using SabreTools.Serialization.Extensions; -using static SabreTools.Models.InstallShieldCabinet.Constants; +using SabreTools.Serialization.Models.InstallShieldCabinet; +using static SabreTools.Serialization.Models.InstallShieldCabinet.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/LZKWAJ.cs b/SabreTools.Serialization/Deserializers/LZKWAJ.cs index 50d3ba13..82196014 100644 --- a/SabreTools.Serialization/Deserializers/LZKWAJ.cs +++ b/SabreTools.Serialization/Deserializers/LZKWAJ.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.LZ; -using static SabreTools.Models.LZ.Constants; +using SabreTools.Serialization.Models.LZ; +using static SabreTools.Serialization.Models.LZ.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/LZQBasic.cs b/SabreTools.Serialization/Deserializers/LZQBasic.cs index eaaf8014..8b46445e 100644 --- a/SabreTools.Serialization/Deserializers/LZQBasic.cs +++ b/SabreTools.Serialization/Deserializers/LZQBasic.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.LZ; -using static SabreTools.Models.LZ.Constants; +using SabreTools.Serialization.Models.LZ; +using static SabreTools.Serialization.Models.LZ.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/LZSZDD.cs b/SabreTools.Serialization/Deserializers/LZSZDD.cs index 0ab76267..cfa24645 100644 --- a/SabreTools.Serialization/Deserializers/LZSZDD.cs +++ b/SabreTools.Serialization/Deserializers/LZSZDD.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.LZ; -using static SabreTools.Models.LZ.Constants; +using SabreTools.Serialization.Models.LZ; +using static SabreTools.Serialization.Models.LZ.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs b/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs index fa8d8a38..de1a9c0f 100644 --- a/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Deserializers/MicrosoftCabinet.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.MicrosoftCabinet; -using static SabreTools.Models.MicrosoftCabinet.Constants; +using SabreTools.Serialization.Models.MicrosoftCabinet; +using static SabreTools.Serialization.Models.MicrosoftCabinet.Constants; namespace SabreTools.Serialization.Deserializers { @@ -227,12 +227,12 @@ namespace SabreTools.Serialization.Deserializers file.FolderIndex = (FolderIndex)data.ReadUInt16LittleEndian(); file.Date = data.ReadUInt16LittleEndian(); file.Time = data.ReadUInt16LittleEndian(); - file.Attributes = (SabreTools.Models.MicrosoftCabinet.FileAttributes)data.ReadUInt16LittleEndian(); + file.Attributes = (SabreTools.Serialization.Models.MicrosoftCabinet.FileAttributes)data.ReadUInt16LittleEndian(); #if NET20 || NET35 - if ((file.Attributes & SabreTools.Models.MicrosoftCabinet.FileAttributes.NAME_IS_UTF) != 0) + if ((file.Attributes & SabreTools.Serialization.Models.MicrosoftCabinet.FileAttributes.NAME_IS_UTF) != 0) #else - if (file.Attributes.HasFlag(SabreTools.Models.MicrosoftCabinet.FileAttributes.NAME_IS_UTF)) + if (file.Attributes.HasFlag(SabreTools.Serialization.Models.MicrosoftCabinet.FileAttributes.NAME_IS_UTF)) #endif file.Name = data.ReadNullTerminatedUnicodeString(); else diff --git a/SabreTools.Serialization/Deserializers/MoPaQ.cs b/SabreTools.Serialization/Deserializers/MoPaQ.cs index 1ebfb3b6..c47c3915 100644 --- a/SabreTools.Serialization/Deserializers/MoPaQ.cs +++ b/SabreTools.Serialization/Deserializers/MoPaQ.cs @@ -3,8 +3,8 @@ using System.IO; using System.Text; using SabreTools.IO.Encryption; using SabreTools.IO.Extensions; -using SabreTools.Models.MoPaQ; -using static SabreTools.Models.MoPaQ.Constants; +using SabreTools.Serialization.Models.MoPaQ; +using static SabreTools.Serialization.Models.MoPaQ.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/NCF.cs b/SabreTools.Serialization/Deserializers/NCF.cs index 65a8e18a..17848d4b 100644 --- a/SabreTools.Serialization/Deserializers/NCF.cs +++ b/SabreTools.Serialization/Deserializers/NCF.cs @@ -2,14 +2,14 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.NCF; +using SabreTools.Serialization.Models.NCF; namespace SabreTools.Serialization.Deserializers { - public class NCF : BaseBinaryDeserializer + public class NCF : BaseBinaryDeserializer { /// - public override SabreTools.Models.NCF.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.NCF.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new Half-Life No Cache to fill - var file = new SabreTools.Models.NCF.File(); + var file = new SabreTools.Serialization.Models.NCF.File(); #region Header diff --git a/SabreTools.Serialization/Deserializers/PAK.cs b/SabreTools.Serialization/Deserializers/PAK.cs index 5cbe4387..be0a09d5 100644 --- a/SabreTools.Serialization/Deserializers/PAK.cs +++ b/SabreTools.Serialization/Deserializers/PAK.cs @@ -1,15 +1,15 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.PAK; -using static SabreTools.Models.PAK.Constants; +using SabreTools.Serialization.Models.PAK; +using static SabreTools.Serialization.Models.PAK.Constants; namespace SabreTools.Serialization.Deserializers { - public class PAK : BaseBinaryDeserializer + public class PAK : BaseBinaryDeserializer { /// - public override SabreTools.Models.PAK.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.PAK.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new Half-Life Package to fill - var file = new SabreTools.Models.PAK.File(); + var file = new SabreTools.Serialization.Models.PAK.File(); #region Header diff --git a/SabreTools.Serialization/Deserializers/PFF.cs b/SabreTools.Serialization/Deserializers/PFF.cs index 6d845597..2ec5de30 100644 --- a/SabreTools.Serialization/Deserializers/PFF.cs +++ b/SabreTools.Serialization/Deserializers/PFF.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.PFF; -using static SabreTools.Models.PFF.Constants; +using SabreTools.Serialization.Models.PFF; +using static SabreTools.Serialization.Models.PFF.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/PKZIP.cs b/SabreTools.Serialization/Deserializers/PKZIP.cs index 9760f9e7..e9cf657b 100644 --- a/SabreTools.Serialization/Deserializers/PKZIP.cs +++ b/SabreTools.Serialization/Deserializers/PKZIP.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.PKZIP; -using static SabreTools.Models.PKZIP.Constants; +using SabreTools.Serialization.Models.PKZIP; +using static SabreTools.Serialization.Models.PKZIP.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/Quantum.cs b/SabreTools.Serialization/Deserializers/Quantum.cs index 8426d2e8..358ed898 100644 --- a/SabreTools.Serialization/Deserializers/Quantum.cs +++ b/SabreTools.Serialization/Deserializers/Quantum.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.Quantum; -using static SabreTools.Models.Quantum.Constants; +using SabreTools.Serialization.Models.Quantum; +using static SabreTools.Serialization.Models.Quantum.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/SGA.cs b/SabreTools.Serialization/Deserializers/SGA.cs index 19c413d4..e6e407eb 100644 --- a/SabreTools.Serialization/Deserializers/SGA.cs +++ b/SabreTools.Serialization/Deserializers/SGA.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.SGA; -using static SabreTools.Models.SGA.Constants; +using SabreTools.Serialization.Models.SGA; +using static SabreTools.Serialization.Models.SGA.Constants; namespace SabreTools.Serialization.Deserializers { @@ -122,7 +122,7 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// SGA major version /// Filled SGA directory on success, null on error - private static SabreTools.Models.SGA.Directory? ParseDirectory(Stream data, ushort majorVersion) + private static SabreTools.Serialization.Models.SGA.Directory? ParseDirectory(Stream data, ushort majorVersion) { return majorVersion switch { diff --git a/SabreTools.Serialization/Deserializers/TapeArchive.cs b/SabreTools.Serialization/Deserializers/TapeArchive.cs index a04a8c53..025220f4 100644 --- a/SabreTools.Serialization/Deserializers/TapeArchive.cs +++ b/SabreTools.Serialization/Deserializers/TapeArchive.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.TAR; +using SabreTools.Serialization.Models.TAR; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/VBSP.cs b/SabreTools.Serialization/Deserializers/VBSP.cs index be00dbc7..2edac80a 100644 --- a/SabreTools.Serialization/Deserializers/VBSP.cs +++ b/SabreTools.Serialization/Deserializers/VBSP.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.BSP; -using static SabreTools.Models.BSP.Constants; +using SabreTools.Serialization.Models.BSP; +using static SabreTools.Serialization.Models.BSP.Constants; // TODO: Finish replacing ReadType namespace SabreTools.Serialization.Deserializers diff --git a/SabreTools.Serialization/Deserializers/VPK.cs b/SabreTools.Serialization/Deserializers/VPK.cs index 8e5d3c4e..c3f2ff94 100644 --- a/SabreTools.Serialization/Deserializers/VPK.cs +++ b/SabreTools.Serialization/Deserializers/VPK.cs @@ -1,15 +1,15 @@ using System.Collections.Generic; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.VPK; -using static SabreTools.Models.VPK.Constants; +using SabreTools.Serialization.Models.VPK; +using static SabreTools.Serialization.Models.VPK.Constants; namespace SabreTools.Serialization.Deserializers { - public class VPK : BaseBinaryDeserializer + public class VPK : BaseBinaryDeserializer { /// - public override SabreTools.Models.VPK.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.VPK.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new Valve Package to fill - var file = new SabreTools.Models.VPK.File(); + var file = new SabreTools.Serialization.Models.VPK.File(); #region Header diff --git a/SabreTools.Serialization/Deserializers/WAD3.cs b/SabreTools.Serialization/Deserializers/WAD3.cs index fc805d36..3b50e9af 100644 --- a/SabreTools.Serialization/Deserializers/WAD3.cs +++ b/SabreTools.Serialization/Deserializers/WAD3.cs @@ -1,15 +1,15 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.WAD3; -using static SabreTools.Models.WAD3.Constants; +using SabreTools.Serialization.Models.WAD3; +using static SabreTools.Serialization.Models.WAD3.Constants; namespace SabreTools.Serialization.Deserializers { - public class WAD3 : BaseBinaryDeserializer + public class WAD3 : BaseBinaryDeserializer { /// - public override SabreTools.Models.WAD3.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.WAD3.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new Half-Life Texture Package to fill - var file = new SabreTools.Models.WAD3.File(); + var file = new SabreTools.Serialization.Models.WAD3.File(); #region Header diff --git a/SabreTools.Serialization/Deserializers/XZP.cs b/SabreTools.Serialization/Deserializers/XZP.cs index 77633b8d..9e998a13 100644 --- a/SabreTools.Serialization/Deserializers/XZP.cs +++ b/SabreTools.Serialization/Deserializers/XZP.cs @@ -1,15 +1,15 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.XZP; -using static SabreTools.Models.XZP.Constants; +using SabreTools.Serialization.Models.XZP; +using static SabreTools.Serialization.Models.XZP.Constants; namespace SabreTools.Serialization.Deserializers { - public class XZP : BaseBinaryDeserializer + public class XZP : BaseBinaryDeserializer { /// - public override SabreTools.Models.XZP.File? Deserialize(Stream? data) + public override SabreTools.Serialization.Models.XZP.File? Deserialize(Stream? data) { // If the data is invalid if (data == null || !data.CanRead) @@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers long initialOffset = data.Position; // Create a new XBox Package File to fill - var file = new SabreTools.Models.XZP.File(); + var file = new SabreTools.Serialization.Models.XZP.File(); #region Header diff --git a/SabreTools.Serialization/Extensions/InstallShieldCabinet.cs b/SabreTools.Serialization/Extensions/InstallShieldCabinet.cs index ed680544..27ee26a9 100644 --- a/SabreTools.Serialization/Extensions/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Extensions/InstallShieldCabinet.cs @@ -1,4 +1,4 @@ -using SabreTools.Models.InstallShieldCabinet; +using SabreTools.Serialization.Models.InstallShieldCabinet; namespace SabreTools.Serialization.Extensions { diff --git a/SabreTools.Serialization/Models/BFPK/Archive.cs b/SabreTools.Serialization/Models/BFPK/Archive.cs new file mode 100644 index 00000000..22b4befb --- /dev/null +++ b/SabreTools.Serialization/Models/BFPK/Archive.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.BFPK +{ + /// + /// BFPK custom archive format + /// + /// + public sealed class Archive + { + /// + /// Header + /// + public Header? Header { get; set; } + + /// + /// Files + /// + public FileEntry[]? Files { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/BFPK/Constants.cs b/SabreTools.Serialization/Models/BFPK/Constants.cs new file mode 100644 index 00000000..0b86ba2b --- /dev/null +++ b/SabreTools.Serialization/Models/BFPK/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BFPK +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x42, 0x46, 0x50, 0x4b]; + + public const string SignatureString = "BFPK"; + + public const uint SignatureUInt32 = 0x4b504642; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BFPK/FileEntry.cs b/SabreTools.Serialization/Models/BFPK/FileEntry.cs new file mode 100644 index 00000000..a563e931 --- /dev/null +++ b/SabreTools.Serialization/Models/BFPK/FileEntry.cs @@ -0,0 +1,34 @@ +namespace SabreTools.Serialization.Models.BFPK +{ + /// + /// File entry + /// + /// + public sealed class FileEntry + { + /// + /// Name size + /// + public int NameSize { get; set; } + + /// + /// Name + /// + public string? Name { get; set; } + + /// + /// Uncompressed size + /// + public int UncompressedSize { get; set; } + + /// + /// Offset + /// + public int Offset { get; set; } + + /// + /// Compressed size + /// + public int CompressedSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/BFPK/Header.cs b/SabreTools.Serialization/Models/BFPK/Header.cs new file mode 100644 index 00000000..998aff6e --- /dev/null +++ b/SabreTools.Serialization/Models/BFPK/Header.cs @@ -0,0 +1,28 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BFPK +{ + /// + /// Header + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// "BFPK" + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Magic; + + /// + /// Version + /// + public int Version; + + /// + /// Files + /// + public int Files; + } +} diff --git a/SabreTools.Serialization/Models/BSP/AmbientIndexLump.cs b/SabreTools.Serialization/Models/BSP/AmbientIndexLump.cs new file mode 100644 index 00000000..79a00984 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/AmbientIndexLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class AmbientIndexLump : Lump + { + /// + /// Indicies + /// + public LeafAmbientIndex[]? Indicies { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/AmbientLightingLump.cs b/SabreTools.Serialization/Models/BSP/AmbientLightingLump.cs new file mode 100644 index 00000000..ca0a0959 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/AmbientLightingLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class AmbientLightingLump : Lump + { + /// + /// Lightings + /// + public LeafAmbientLighting[]? Lightings { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Brush.cs b/SabreTools.Serialization/Models/BSP/Brush.cs new file mode 100644 index 00000000..295126d2 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Brush.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The brush lump (Lump 18) contains all brushes that were + /// present in the original VMF file before compiling. + /// Unlike faces, brushes are constructive solid geometry (CSG) + /// defined by planes instead of edges and vertices. It is the + /// presence of the brush and brushside lumps in Source BSP + /// files that makes decompiling them a much easier job than + /// for GoldSrc files, which lacked this info. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Brush + { + /// + /// First brushside + /// + public int FirstSide; + + /// + /// Number of brushsides + /// + public int NumSides; + + /// + /// Contents flags + /// + public VbspContents Contents; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BrushesLump.cs b/SabreTools.Serialization/Models/BSP/BrushesLump.cs new file mode 100644 index 00000000..dc725de7 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BrushesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BrushesLump : Lump + { + /// + /// Brushes + /// + public Brush[]? Brushes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Brushside.cs b/SabreTools.Serialization/Models/BSP/Brushside.cs new file mode 100644 index 00000000..e2c29ccc --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Brushside.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Planenum is an index info the plane array, giving the plane + /// corresponding to this brushside. Texinfo and dispinfo are + /// references into the texture and displacement info lumps. + /// Bevel is zero for normal brush sides, but 1 if the side is + /// a bevel plane (which seem to be used for collision detection). + /// + /// Unlike the face array, brushsides are not culled (removed) + /// where they touch the void. Void-facing sides do however have + /// their texinfo entry changed to the tools/toolsnodraw texture + /// during the compile process. Note there is no direct way of + /// linking brushes and brushsides and the corresponding face array + /// entries which are used to render that brush. Brushsides are + /// used by the engine to calculate all player physics collision + /// with world brushes. (Vphysics objects use lump 29 instead.) + /// + /// The maximum number of brushsides is 65536 (MAX_MAP_BRUSHSIDES). + /// The maximum number of brushsides on a single brush is 128 (MAX_BRUSH_SIDES). + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Brushside + { + /// + /// Facing out of the leaf + /// + public ushort PlaneNum; + + /// + /// Texture info + /// + public short TextureInfo; + + /// + /// Displacement info + /// + public short DisplacementInfo; + + /// + /// Is the side a bevel plane? + /// + public short Bevel; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BrushsidesLump.cs b/SabreTools.Serialization/Models/BSP/BrushsidesLump.cs new file mode 100644 index 00000000..eadafbef --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BrushsidesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BrushsidesLump : Lump + { + /// + /// Brushsides + /// + public Brushside[]? Brushsides { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspFace.cs b/SabreTools.Serialization/Models/BSP/BspFace.cs new file mode 100644 index 00000000..fca609d7 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspFace.cs @@ -0,0 +1,66 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The face lump contains the surfaces of the scene. + /// + /// The first number of this data structure is an index into + /// the planes lump giving a plane which is parallel to this + /// face (meaning they share the same normal). The second + /// value may be seen as a boolean. If nPlaneSide equals 0, + /// then the normal vector of this face equals the one of the + /// parallel plane exactly. Otherwise, the normal of the plane + /// has to be multiplied by -1 to point into the right direction. + /// Afterwards we have an index into the surfedges lump, as + /// well as the count of consecutive surfedges from that position. + /// Furthermore there is an index into the texture info lump, + /// which is used to find the BSPTEXINFO structure needed to + /// calculate the texture coordinates for this face. Afterwards, + /// there are four bytes giving some lighting information (partly + /// used by the renderer to hide sky surfaces). Finally we have + /// an offset in byes giving the beginning of the binary lightmap + /// data of this face in the lighting lump. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BspFace + { + /// + /// Plane the face is parallel to + /// + public ushort PlaneIndex; + + /// + /// Set if different normals orientation + /// + public ushort PlaneSideCount; + + /// + /// Index of the first surfedge + /// + public uint FirstEdgeIndex; + + /// + /// Number of consecutive surfedges + /// + public ushort NumberOfEdges; + + /// + /// Index of the texture info structure + /// + public ushort TextureInfoIndex; + + /// + /// Specify lighting styles + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[]? LightingStyles = new byte[4]; + + /// + /// Offsets into the raw lightmap data; if less than zero, + /// then a lightmap was not baked for the given face. + /// + public int LightmapOffset; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspFacesLump.cs b/SabreTools.Serialization/Models/BSP/BspFacesLump.cs new file mode 100644 index 00000000..2cdfe5af --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspFacesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BspFacesLump : Lump + { + /// + /// Faces + /// + public BspFace[]? Faces { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspFile.cs b/SabreTools.Serialization/Models/BSP/BspFile.cs new file mode 100644 index 00000000..b4649ac5 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspFile.cs @@ -0,0 +1,94 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Half-Life Level + /// + /// + /// + public sealed class BspFile + { + /// + /// Header data + /// + public BspHeader? Header { get; set; } + + #region Lumps + + /// + /// LUMP_ENTITIES [0] + /// + public EntitiesLump? Entities { get; set; } + + /// + /// LUMP_PLANES [1] + /// + public PlanesLump? PlanesLump { get; set; } + + /// + /// LUMP_TEXTURES [2] + /// + public TextureLump? TextureLump { get; set; } + + /// + /// LUMP_VERTICES [3] + /// + public VerticesLump? VerticesLump { get; set; } + + /// + /// LUMP_VISIBILITY [4] + /// + public VisibilityLump? VisibilityLump { get; set; } + + /// + /// LUMP_NODES [5] + /// + public BspNodesLump? NodesLump { get; set; } + + /// + /// LUMP_TEXINFO [6] + /// + public BspTexinfoLump? TexinfoLump { get; set; } + + /// + /// LUMP_FACES [7] + /// + public BspFacesLump? FacesLump { get; set; } + + /// + /// LUMP_LIGHTING [8] + /// + public LightmapLump? LightmapLump { get; set; } + + /// + /// LUMP_CLIPNODES [9] + /// s + public ClipnodesLump? ClipnodesLump { get; set; } + + /// + /// LUMP_LEAVES [10] + /// + public BspLeavesLump? LeavesLump { get; set; } + + /// + /// LUMP_MARKSURFACES [11] + /// + public MarksurfacesLump? MarksurfacesLump { get; set; } + + /// + /// LUMP_EDGES [12] + /// + public EdgesLump? EdgesLump { get; set; } + + /// + /// LUMP_SURFEDGES [13] + /// + public SurfedgesLump? SurfedgesLump { get; set; } + + /// + /// LUMP_MODELS [14] + /// + public BspModelsLump? ModelsLump { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspHeader.cs b/SabreTools.Serialization/Models/BSP/BspHeader.cs new file mode 100644 index 00000000..a54ecee1 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspHeader.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BspHeader + { + /// + /// Version + /// + /// Must be 30 for a valid HL BSP file + public int Version; + + /// + /// Lumps + /// + /// 15 entries + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.BSP_HEADER_LUMPS)] + public BspLumpEntry[]? Lumps; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspLeaf.cs b/SabreTools.Serialization/Models/BSP/BspLeaf.cs new file mode 100644 index 00000000..e097bca1 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspLeaf.cs @@ -0,0 +1,67 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The leaves lump contains the leaves of the BSP tree. + /// + /// The first entry of this struct is the type of the content + /// of this leaf. It can be one of the predefined values, found + /// in the compiler source codes, and is litte relevant for the + /// actual rendering process. All the more important is the + /// next integer containing the offset into the vis lump. It + /// defines the start of the raw PVS data for this leaf. If this + /// value equals -1, no VIS lists are available for this leaf, + /// usually if the map has been built without the VIS compiler. + /// The next two 16bit integer triples span the bounding box of + /// this leaf. Furthermore, the struct contains an index pointing + /// into the array of marksurfaces loaded from the marksufaces + /// lump as well as the number of consecutive marksurfaces belonging + /// to this leaf. The marksurfaces are looped through during the + /// rendering process and point to the actual faces. The final 4 bytes + /// specify the volume of ambient sounds in Quake, but are unused in + /// GoldSrc. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BspLeaf + { + /// + /// Contents enumeration + /// + public BspContents Contents; + + /// + /// Offset into the visibility lump + /// + public int VisOffset; + + /// + /// Defines bounding box + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public short[] Mins = new short[3]; + + /// + /// Defines bounding box + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public short[] Maxs = new short[3]; + + /// + /// Index into marksurfaces array + /// + public ushort FirstMarkSurfaceIndex; + + /// + /// Count of marksurfaces array + /// + public ushort MarkSurfacesCount; + + /// + /// Ambient sound levels + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[]? AmbientLevels = new byte[4]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspLeavesLump.cs b/SabreTools.Serialization/Models/BSP/BspLeavesLump.cs new file mode 100644 index 00000000..ea8cde8f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspLeavesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BspLeavesLump : Lump + { + /// + /// Leaves + /// + public BspLeaf[]? Leaves { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspLumpEntry.cs b/SabreTools.Serialization/Models/BSP/BspLumpEntry.cs new file mode 100644 index 00000000..04af9c09 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspLumpEntry.cs @@ -0,0 +1,20 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class BspLumpEntry + { + /// + /// File offset to data + /// + public int Offset; + + /// + /// Length of data + /// + public int Length; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspModel.cs b/SabreTools.Serialization/Models/BSP/BspModel.cs new file mode 100644 index 00000000..f3f6aecd --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspModel.cs @@ -0,0 +1,63 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// A model is kind of a mini BSP tree. Its size is determinded + /// by the bounding box spaned by the first to members of this + /// struct. The major difference between a model and the BSP + /// tree holding the scene is that the models use a local + /// coordinate system for their vertexes and just state its + /// origin in world coordinates. During rendering the coordinate + /// system is translated to the origin of the model (glTranslate()) + /// and moved back after the models BSP tree has been traversed. + /// Furthermore their are 4 indexes into node arrays. The first + /// one has proofed to index the root node of the mini BSP tree + /// used for rendering. The other three indexes could probably be + /// used for collision detection, meaning they point into the + /// clipnodes, but I am not sure about this. The meaning of the + /// next value is also somehow unclear to me. Finally their are + /// direct indexes into the faces array, not taking the redirecting + /// by the marksurfaces. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BspModel + { + /// + /// Defines bounding box + /// + public Vector3D? Mins; + + /// + /// Defines bounding box + /// + public Vector3D? Maxs; + + /// + /// Coordinates to move the coordinate system + /// + public Vector3D? OriginVector; + + /// + /// Index into nodes array + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MAX_MAP_HULLS)] + public int[]? HeadnodesIndex = new int[Constants.MAX_MAP_HULLS]; + + /// + /// ??? + /// + public int VisLeafsCount; + + /// + /// Index into faces + /// + public int FirstFaceIndex; + + /// + /// Count of faces + /// + public int FacesCount; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspModelsLump.cs b/SabreTools.Serialization/Models/BSP/BspModelsLump.cs new file mode 100644 index 00000000..b933726e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspModelsLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BspModelsLump : Lump + { + /// + /// Model + /// + public BspModel[]? Models { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspNode.cs b/SabreTools.Serialization/Models/BSP/BspNode.cs new file mode 100644 index 00000000..dd53b7b0 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspNode.cs @@ -0,0 +1,62 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This lump is simple again and contains an array of binary + /// structures, the nodes, which are a major part of the BSP tree. + /// + /// Every BSPNODE structure represents a node in the BSP tree and + /// every node equals more or less a division step of the BSP algorithm. + /// Therefore, each node has an index (iPlane) referring to a plane + /// in the plane lump which devides the node into its two child nodes. + /// The childnodes are also stored as indexes. Contrary to the plane + /// index, the node index for the child is signed. If the index is + /// larger than 0, the index indicates a child node. If it is equal + /// to or smaller than zero (no valid array index), the bitwise + /// inversed value of the index gives an index into the leaves lump. + /// Additionally two points (nMins, nMaxs) span the bounding box + /// (AABB, axis aligned bounding box) delimitting the space of the node. + /// Finally firstFace indexes into the face lump and spezifies the + /// first of nFaces surfaces contained in this node. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class BspNode + { + /// + /// Index into Planes lump + /// + public uint PlaneIndex; + + /// + /// If > 0, then indices into Nodes. + /// Otherwise bitwise inverse indices into Leafs + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public ushort[] Children = new ushort[2]; + + /// + /// Defines bounding box + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public ushort[] Mins = new ushort[3]; + + /// + /// Defines bounding box + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public ushort[] Maxs = new ushort[3]; + + /// + /// Index into Faces + /// + public ushort FirstFace; + + /// + /// Count of Faces + /// + public ushort FaceCount; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspNodesLump.cs b/SabreTools.Serialization/Models/BSP/BspNodesLump.cs new file mode 100644 index 00000000..78f4d22e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspNodesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BspNodesLump : Lump + { + /// + /// Nodes + /// + public BspNode[]? Nodes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspTexinfo.cs b/SabreTools.Serialization/Models/BSP/BspTexinfo.cs new file mode 100644 index 00000000..680e8cf9 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspTexinfo.cs @@ -0,0 +1,52 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The texinfo lump contains informations about how textures are + /// applied to surfaces. The lump itself is an array of binary data + /// structures. + /// + /// This struct is mainly responsible for the calculation of the texture + /// coordinates (vS, fSShift, vT, fTShift). This values determine the + /// position of the texture on the surface. The iMiptex integer refers + /// to the textures in the texture lump and would be the index in an + /// array of BSPMITEX structs. Finally, there are 4 Bytes used for flags. + /// Only one flag is used by the vanilla engine, being 0x1 for disabling + /// lightmaps and subdivision for the surface (used by sky and liquids). + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BspTexinfo + { + /// + /// S-vector + /// + public Vector3D? SVector; + + /// + /// Texture shift in the S direction + /// + public float TextureSShift; + + /// + /// T-vector + /// + public Vector3D? TVector; + + /// + /// Texture shift in the T direction + /// + public float TextureTShift; + + /// + /// Index into textures array + /// + public uint MiptexIndex; + + /// + /// Texture flags + /// + public TextureFlag Flags; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/BspTexinfoLump.cs b/SabreTools.Serialization/Models/BSP/BspTexinfoLump.cs new file mode 100644 index 00000000..e7340c61 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/BspTexinfoLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class BspTexinfoLump : Lump + { + /// + /// Texinfos + /// + public BspTexinfo[]? Texinfos { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/CDispCornerNeighbors.cs b/SabreTools.Serialization/Models/BSP/CDispCornerNeighbors.cs new file mode 100644 index 00000000..294342ab --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/CDispCornerNeighbors.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class CDispCornerNeighbors + { + /// + /// Indices of neighbors. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public ushort[] Neighbors = new ushort[4]; + + public byte NeighborCount; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/CDispNeighbor.cs b/SabreTools.Serialization/Models/BSP/CDispNeighbor.cs new file mode 100644 index 00000000..7064b46b --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/CDispNeighbor.cs @@ -0,0 +1,12 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class CDispNeighbor + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public CDispSubNeighbor[]? SubNeighbors = new CDispSubNeighbor[2]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/CDispSubNeighbor.cs b/SabreTools.Serialization/Models/BSP/CDispSubNeighbor.cs new file mode 100644 index 00000000..295d1c5b --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/CDispSubNeighbor.cs @@ -0,0 +1,32 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class CDispSubNeighbor + { + /// + /// This indexes into ddispinfos. + /// + /// 0xFFFF if there is no neighbor here. + public ushort NeighborIndex; + + /// + /// (CCW) rotation of the neighbor wrt this displacement. + /// + public byte NeighborOrientation; + + // These use the NeighborSpan type. + + /// + /// Where the neighbor fits onto this side of our displacement. + /// + public byte Span; + + /// + /// Where we fit onto our neighbor. + /// + public byte NeighborSpan; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Clipnode.cs b/SabreTools.Serialization/Models/BSP/Clipnode.cs new file mode 100644 index 00000000..1efa63e2 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Clipnode.cs @@ -0,0 +1,28 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This lump contains the so-called clipnodes, which build a second + /// BSP tree used only for collision detection. + /// + /// This structure is a reduced form of the BSPNODE struct from the + /// nodes lump. Also the BSP tree built by the clipnodes is simpler + /// than the one described by the BSPNODEs to accelerate collision calculations. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Clipnode + { + /// + /// Index into planes + /// + public int PlaneIndex; + + /// + /// Negative numbers are contents + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public short[]? ChildrenIndices = new short[2]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/ClipnodesLump.cs b/SabreTools.Serialization/Models/BSP/ClipnodesLump.cs new file mode 100644 index 00000000..ed4dab6a --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/ClipnodesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class ClipnodesLump : Lump + { + /// + /// Clipnodes + /// + public Clipnode[]? Clipnodes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/ColorRGBExp32.cs b/SabreTools.Serialization/Models/BSP/ColorRGBExp32.cs new file mode 100644 index 00000000..a2f932aa --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/ColorRGBExp32.cs @@ -0,0 +1,20 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// 4-byte lightmap structure + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class ColorRGBExp32 + { + public byte Red; + + public byte Green; + + public byte Blue; + + public sbyte Exponent; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/CompressedLightCube.cs b/SabreTools.Serialization/Models/BSP/CompressedLightCube.cs new file mode 100644 index 00000000..d1c7d0ac --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/CompressedLightCube.cs @@ -0,0 +1,16 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The lighting data for each sample is represented by an array + /// of 6 ColorRGBExp32 + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class CompressedLightCube + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public ColorRGBExp32[]? Colors; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Constants.cs b/SabreTools.Serialization/Models/BSP/Constants.cs new file mode 100644 index 00000000..6c0e0912 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Constants.cs @@ -0,0 +1,100 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + public static class Constants + { + #region Header + + /// + /// Number of lumps in a BSP + /// + public const int BSP_HEADER_LUMPS = 15; + + /// + /// Number of lumps in a VBSP + /// + public const int VBSP_HEADER_LUMPS = 64; + + #endregion + + #region Lump + + public const int MAX_MAP_HULLS = 4; + + public const int MAX_MAP_MODELS = 400; + public const int MAX_MAP_BRUSHES = 4096; + public const int MAX_MAP_ENTITIES = 1024; + public const int MAX_MAP_ENTSTRING = (128 * 1024); + + public const int MAX_MAP_PLANES = 32767; + public const int MAX_MAP_NODES = 32767; + public const int MAX_MAP_CLIPNODES = 32767; + public const int MAX_MAP_LEAFS = 8192; + public const int MAX_MAP_VERTS = 65535; + public const int MAX_MAP_FACES = 65535; + public const int MAX_MAP_MARKSURFACES = 65535; + public const int MAX_MAP_TEXINFO = 8192; + public const int MAX_MAP_EDGES = 256000; + public const int MAX_MAP_SURFEDGES = 512000; + public const int MAX_MAP_TEXTURES = 512; + public const int MAX_MAP_MIPTEX = 0x200000; + public const int MAX_MAP_LIGHTING = 0x200000; + public const int MAX_MAP_VISIBILITY = 0x200000; + + public const int MAX_MAP_PORTALS = 65536; + + #endregion + + #region Entities + + public const int MAX_KEY = 32; + + public const int MAX_VALUE = 1024; + + #endregion + + #region Textures + + public const int MAXTEXTURENAME = 16; + + public const int MIPLEVELS = 4; + + #endregion + + #region VBSP + + public static readonly byte[] SignatureBytes = [0x56, 0x42, 0x53, 0x50]; + + public const string SignatureString = "VBSP"; + + public const uint SignatureUInt32 = 0x50534256; + + #endregion + + #region LZMA + + public static readonly byte[] LzmaHeaderBytes = [0x4C, 0x5A, 0x4D, 0x41]; + + public const string LzmaHeaderString = "LZMA"; + + public const uint LzmaHeaderUInt32 = 0x414D5A4C; + + #endregion + + #region Overlay + + public const int OVERLAY_BSP_FACE_COUNT = 64; + + #endregion + + #region Worldlights + + /// + /// This says that the light was put into the per-leaf ambient cubes. + /// + public const int DWL_FLAGS_INAMBIENTCUBE = 0x0001; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Cubemap.cs b/SabreTools.Serialization/Models/BSP/Cubemap.cs new file mode 100644 index 00000000..5276d26e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Cubemap.cs @@ -0,0 +1,50 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The dcubemapsample_t structure defines the location of a + /// env_cubemap entity in the map. The origin member contains + /// integer x,y,z coordinates of the cubemap, and the size member + /// is resolution of the cubemap, specified as 2^(size-1) pixels + /// square. If set as 0, the default size of 6 (32x32 pixels) is + /// used. There can be a maximum of 1024 (MAX_MAP_CUBEMAPSAMPLES) + /// cubemaps in a file. + /// + /// When the "buildcubemaps" console command is performed, six + /// snapshots of the map (one for each direction) are taken at the + /// location of each env_cubemap entity. These snapshots are stored + /// in a multi-frame texture (vtf) file, which is added to the + /// Pakfile lump (see above). The textures are named cX_Y_Z.vtf, + /// where (X,Y,Z) are the (integer) coordinates of the corresponding + /// cubemap. + /// + /// Faces containing materials that are environment mapped (e.g. + /// shiny textures) reference their assigned cubemap through their + /// material name. A face with a material named (e.g.) walls/shiny.vmt + /// is altered (new Texinfo & Texdata entries are created) to refer + /// to a renamed material maps/mapname/walls/shiny_X_Y_Z.vmt, where + /// (X,Y,Z) are the cubemap coordinates as before. This .vmt file + /// is also stored in the Pakfile, and references the cubemap .vtf + /// file through its $envmap property. + /// + /// Version 20 files contain extra cX_Y_Z.hdr.vtf files in the + /// Pakfile lump, containing HDR texture files in RGBA16161616F + /// (16-bit per channel) format. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Cubemap + { + /// + /// Position of light snapped to the nearest integer + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public int[]? Origin = new int[3]; + + /// + /// Resolution of cubemap, 0 - default + /// + public int Size; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/CubemapsLump.cs b/SabreTools.Serialization/Models/BSP/CubemapsLump.cs new file mode 100644 index 00000000..710bd4fa --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/CubemapsLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class CubemapsLump : Lump + { + /// + /// Cubemaps + /// + public Cubemap[]? Cubemaps { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispInfo.cs b/SabreTools.Serialization/Models/BSP/DispInfo.cs new file mode 100644 index 00000000..e2ba4582 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispInfo.cs @@ -0,0 +1,93 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The structure is 176 bytes long. The startPosition element is the + /// coordinates of the first corner of the displacement. DispVertStart + /// and DispTriStart are indices into the DispVerts and DispTris lumps. + /// The power entry gives the number of subdivisions in the displacement + /// surface - allowed values are 2, 3 and 4, and these correspond to 4, + /// 8 and 16 subdivisions on each side of the displacement surface. + /// The structure also references any neighbouring displacements on the + /// sides or the corners of this displacement through the EdgeNeighbors + /// and CornerNeighbors members. There are complex rules governing the + /// order that these neighbour displacements are given; see the comments + /// in bspfile.h for more. The MapFace value is an index into the face + /// array and is face that was turned into a displacement surface. + /// This face is used to set the texture and overall physical location + /// and boundaries of the displacement. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DispInfo + { + /// + /// Start position used for orientation + /// + public Vector3D? StartPosition; + + /// + /// Index into LUMP_DISP_VERTS. + /// + public int DispVertStart; + + /// + /// Index into LUMP_DISP_TRIS. + /// + public int DispTriStart; + + /// + /// Power - indicates size of surface (2^power 1) + /// + public int Power; + + /// + /// Minimum tesselation allowed + /// + public int MinTess; + + /// + /// Lighting smoothing angle + /// + public float SmoothingAngle; + + /// + /// Surface contents + /// + public int Contents; + + /// + /// Which map face this displacement comes from. + /// + public ushort MapFace; + + /// + /// Index into ddisplightmapalpha. + /// + public int LightmapAlphaStart; + + /// + /// Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS. + /// + public int LightmapSamplePositionStart; + + /// + /// Indexed by NEIGHBOREDGE_ defines. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public CDispNeighbor[]? EdgeNeighbors = new CDispNeighbor[4]; + + /// + /// Indexed by CORNER_ defines. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public CDispCornerNeighbors[]? CornerNeighbors = new CDispCornerNeighbors[4]; + + /// + /// Active verticies + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public uint[]? AllowedVerts = new uint[10]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispInfosLump.cs b/SabreTools.Serialization/Models/BSP/DispInfosLump.cs new file mode 100644 index 00000000..813930d3 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispInfosLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class DispInfosLump : Lump + { + /// + /// Infos + /// + public DispInfo[]? Infos { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispTri.cs b/SabreTools.Serialization/Models/BSP/DispTri.cs new file mode 100644 index 00000000..8b8fa494 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispTri.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// he DispTris lump (Lump 48) contains "triangle tags" or flags + /// related to the properties of a particular triangle in the + /// displacement mesh. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DispTri + { + /// + /// Displacement triangle tags. + /// + public DispTriTag Tags; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispTrisLump.cs b/SabreTools.Serialization/Models/BSP/DispTrisLump.cs new file mode 100644 index 00000000..dcb59779 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispTrisLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class DispTrisLump : Lump + { + /// + /// Tris + /// + public DispTri[]? Tris { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispVert.cs b/SabreTools.Serialization/Models/BSP/DispVert.cs new file mode 100644 index 00000000..24028437 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispVert.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The DispVerts lump (Lump 33) contains the vertex data of the displacements. + /// vec is the normalized vector of the offset of each displacement vertex from + /// its original (flat) position; dist is the distance the offset has taken + /// place; and alpha is the alpha-blending of the texture at that vertex. + /// + /// A displacement of power p references (2^p + 1)^2 dispverts in the array, + /// starting from the DispVertStart index. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DispVert + { + /// + /// Vector field defining displacement volume. + /// + public Vector3D? Vec; + + /// + /// Displacement distances. + /// + public float Dist; + + /// + /// "Per vertex" alpha values. + /// + public float Alpha; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/DispVertsLump.cs b/SabreTools.Serialization/Models/BSP/DispVertsLump.cs new file mode 100644 index 00000000..6ab6bb1e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/DispVertsLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class DispVertsLump : Lump + { + /// + /// Verts + /// + public DispVert[]? Verts { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Edge.cs b/SabreTools.Serialization/Models/BSP/Edge.cs new file mode 100644 index 00000000..7ebc763d --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Edge.cs @@ -0,0 +1,20 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The edges delimit the face and further refer to the vertices of the + /// face. Each edge is pointing to the start and end vertex of the edge. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Edge + { + /// + /// Indices into vertex array + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public ushort[]? VertexIndices = new ushort[2]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/EdgesLump.cs b/SabreTools.Serialization/Models/BSP/EdgesLump.cs new file mode 100644 index 00000000..1add9d3c --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/EdgesLump.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + public sealed class EdgesLump : Lump + { + /// + /// Edge + /// + public Edge[]? Edges { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/EntitiesLump.cs b/SabreTools.Serialization/Models/BSP/EntitiesLump.cs new file mode 100644 index 00000000..f8cd0a8f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/EntitiesLump.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + public sealed class EntitiesLump : Lump + { + /// + /// Entities + /// + public Entity[]? Entities { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Entity.cs b/SabreTools.Serialization/Models/BSP/Entity.cs new file mode 100644 index 00000000..60d80e58 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Entity.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The entity lump is basically a pure ASCII text section. + /// It consists of the string representations of all entities, + /// which are copied directly from the input file to the output + /// BSP file by the compiler. + /// + /// Every entity begins and ends with curly brackets. In between + /// there are the attributes of the entity, one in each line, + /// which are pairs of strings enclosed by quotes. The first + /// string is the name of the attribute (the key), the second one + /// its value. The attribute "classname" is mandatory for every + /// entity specifiying its type and therefore, how it is + /// interpreted by the engine. + /// + /// + /// + public sealed class Entity + { + /// + /// Entity attributes + /// + public List>? Attributes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Enums.cs b/SabreTools.Serialization/Models/BSP/Enums.cs new file mode 100644 index 00000000..cb29ec1f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Enums.cs @@ -0,0 +1,926 @@ +using System; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + public enum BspContents : int + { + CONTENTS_EMPTY = -1, + CONTENTS_SOLID = -2, + CONTENTS_WATER = -3, + CONTENTS_SLIME = -4, + CONTENTS_LAVA = -5, + CONTENTS_SKY = -6, + CONTENTS_ORIGIN = -7, + CONTENTS_CLIP = -8, + CONTENTS_CURRENT_0 = -9, + CONTENTS_CURRENT_90 = -10, + CONTENTS_CURRENT_180 = -11, + CONTENTS_CURRENT_270 = -12, + CONTENTS_CURRENT_UP = -13, + CONTENTS_CURRENT_DOWN = -14, + CONTENTS_TRANSLUCENT = -15, + } + + /// + [Flags] + public enum VbspContents : uint + { + /// + /// No contents + /// + CONTENTS_EMPTY = 0x00000000, + + /// + /// An eye is never valid in a solid + /// + CONTENTS_SOLID = 0x00000001, + + /// + /// Translucent, but not watery (glass) + /// + CONTENTS_WINDOW = 0x00000002, + + /// + /// Unused + /// + CONTENTS_AUX = 0x00000004, + + /// + /// Alpha-tested "grate" textures. Bullets/sight pass through, + /// but solids don't + /// + CONTENTS_GRATE = 0x00000008, + + /// + /// Set via %CompileSlime. Unlike Quake II, slime does not do + /// damage; a separate trigger_hurt should be used for this. + /// + CONTENTS_SLIME = 0x00000010, + + /// + /// Set via %CompileWater. + /// + CONTENTS_WATER = 0x00000020, + + /// + /// Unknown purpose; only set by %CompilePlayerControlClip. + /// + CONTENTS_MIST = 0x00000040, + + /// + /// Block AI line of sight + /// + CONTENTS_BLOCKLOS = 0x00000040, + + /// + /// Things that cannot be seen through (may be non-solid though) + /// + CONTENTS_OPAQUE = 0x00000080, + + /// + /// Unknown + /// + CONTENTS_TESTFOGVOLUME = 0x00000100, + + /// + /// Unused + /// + CONTENTS_UNUSED = 0x00000200, + + /// + /// Unused + /// + CONTENTS_UNUSED6 = 0x00000400, + + /// + /// If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS + /// if not visible, then grab from the bottom. + /// + CONTENTS_BLOCKLIGHT = 0x00000400, + + /// + /// Per team contents used to differentiate collisions + /// between players and objects on different teams + /// + CONTENTS_TEAM1 = 0x00000800, + + /// + /// Per team contents used to differentiate collisions + /// between players and objects on different teams + /// + CONTENTS_TEAM2 = 0x00001000, + + /// + /// Ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW + /// + CONTENTS_IGNORE_NODRAW_OPAQUE = 0x00002000, + + /// + /// Hits entities which are MOVETYPE_PUSH (doors, plats, etc.) + /// + CONTENTS_MOVEABLE = 0x00004000, + + /// + /// Is an areaportal. + /// + CONTENTS_AREAPORTAL = 0x00008000, + + /// + /// Solid to players, including bots. + /// + CONTENTS_PLAYERCLIP = 0x00010000, + + /// + /// Solid to monsters, better known in Source as NPCs. Also solid + /// to bots in CSGO, even though they are players. + /// + CONTENTS_MONSTERCLIP = 0x00020000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_0 = 0x00040000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_90 = 0x00080000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_180 = 0x00100000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_270 = 0x00200000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_UP = 0x00400000, + + /// + /// Currents can be added to any other contents, and may be mixed + /// + CONTENTS_CURRENT_DOWN = 0x00800000, + + /// + /// Unknown + /// + CONTENTS_BRUSH_PAINT = 0x00040000, + + /// + /// Unknown + /// + CONTENTS_GRENADECLIP = 0x00080000, + + /// + /// Unknown + /// + CONTENTS_DRONECLIP = 0x00100000, + + /// + /// Removed before bsping an entity + /// + CONTENTS_ORIGIN = 0x01000000, + + /// + /// Should never be on a brush, only in game + /// + CONTENTS_MONSTER = 0x02000000, + + /// + /// Solid to point traces (ex hitscan weapons) and non-debris + /// physics objects[confirm]. Non-solid to QPhysics entities, + /// such as players. + /// + CONTENTS_DEBRIS = 0x04000000, + + /// + /// Brushes to be added after vis leafs + /// + CONTENTS_DETAIL = 0x08000000, + + /// + /// Auto set if any surface has trans + /// + CONTENTS_TRANSLUCENT = 0x10000000, + + /// + /// Is a ladder + /// + CONTENTS_LADDER = 0x20000000, + + /// + /// Use accurate hitboxes on trace + /// + CONTENTS_HITBOX = 0x40000000, + } + + /// + [Flags] + public enum DispTriTag : ushort + { + DISPTRI_TAG_SURFACE = 0x01, + DISPTRI_TAG_WALKABLE = 0x02, + DISPTRI_TAG_BUILDABLE = 0x04, + DISPTRI_FLAG_SURFPROP1 = 0x08, + DISPTRI_FLAG_SURFPROP2 = 0x10, + } + + /// + public enum EmitType + { + /// + /// 90 degree spotlight + /// + EMIT_SURFACE, + + /// + /// Simple point light source + /// + EMIT_POINT, + + /// + /// Spotlight with penumbra + /// + EMIT_SPOTLIGHT, + + /// + /// Directional light with no falloff + /// (surface must trace to SKY texture) + /// + EMIT_SKYLIGHT, + + /// + /// Linear falloff, non-lambertian + /// + EMIT_QUAKELIGHT, + + /// + /// Spherical light source with no falloff + /// (surface must trace to SKY texture) + /// + EMIT_SKYAMBIENT, + } + + /// + /// + public enum LumpType : int + { + #region BSP and VBSP + + /// + /// The entity lump is basically a pure ASCII text section. + /// It consists of the string representations of all entities, + /// which are copied directly from the input file to the output + /// BSP file by the compiler. + /// + LUMP_ENTITIES = 0, + + /// + /// This lump is a simple array of binary data structures. + /// Each of this structures defines a plane in 3-dimensional + /// space by using the Hesse normal form + /// + LUMP_PLANES = 1, + + /// + /// The texture lump is somehow a bit more complex then the + /// other lumps, because it is possible to save textures + /// directly within the BSP file instead of storing them in + /// external WAD files. + /// + /// LUMP_TEXDATA in VBSP + LUMP_TEXTURES = 2, + + /// + /// This lump simply consists of all vertices of the BSP tree. + /// They are stored as a primitve array of triples of floats. + /// + /// LUMP_VERTEXES in VBSP + LUMP_VERTICES = 3, + + /// + /// The VIS lump contains data, which is irrelevant to the actual + /// BSP tree, but offers a way to boost up the speed of the + /// renderer significantly. Especially complex maps profit from + /// the use if this data. This lump contains the so-called + /// Potentially Visible Sets (PVS) (also called VIS lists) in the + /// same amout of leaves of the tree, the user can enter (often + /// referred to as VisLeaves). The visiblilty lists are stored as + /// sequences of bitfields, which are run-length encoded. + /// + LUMP_VISIBILITY = 4, + + /// + /// This lump is simple again and contains an array of binary + /// structures, the nodes, which are a major part of the BSP tree. + /// + LUMP_NODES = 5, + + /// + /// The texinfo lump contains informations about how textures are + /// applied to surfaces. The lump itself is an array of binary data + /// structures. + /// + LUMP_TEXINFO = 6, + + /// + /// The face lump contains the surfaces of the scene. + /// + LUMP_FACES = 7, + + /// + /// This is one of the largest lumps in the BSP file. The lightmap + /// lump stores all lightmaps used in the entire map. The lightmaps + /// are arrays of triples of bytes (3 channel color, RGB) and stored + /// continuously. + /// + LUMP_LIGHTING = 8, + + /// + /// This lump contains the so-called clipnodes, which build a second + /// BSP tree used only for collision detection. + /// + /// LUMP_OCCLUSION in VBSP + LUMP_CLIPNODES = 9, + + /// + /// The leaves lump contains the leaves of the BSP tree. + /// + /// LUMP_LEAFS in VBSP + LUMP_LEAVES = 10, + + /// + /// The marksurfaces lump is a simple array of short integers. + /// + /// LUMP_FACEIDS in VBSP + LUMP_MARKSURFACES = 11, + + /// + /// The edges delimit the face and further refer to the vertices of the + /// face. Each edge is pointing to the start and end vertex of the edge. + /// + LUMP_EDGES = 12, + + /// + /// This lump represents pretty much the same mechanism as the marksurfaces. + /// A face can insert its surfedge indexes into this array to get the + /// corresponding edges delimitting the face and further pointing to the + /// vertexes, which are required for rendering. The index can be positive + /// or negative. If the value of the surfedge is positive, the first vertex + /// of the edge is used as vertex for rendering the face, otherwise, the + /// value is multiplied by -1 and the second vertex of the indexed edge is + /// used. + /// + LUMP_SURFEDGES = 13, + + /// + /// A model is kind of a mini BSP tree. Its size is determinded by the + /// bounding box spaned by the first to members of this struct. + /// + LUMP_MODELS = 14, + + #endregion + + #region VBSP Only + + /// + /// Internal world lights converted from the entity lump + /// + LUMP_WORLDLIGHTS = 15, + + /// + /// Index to faces in each leaf + /// + LUMP_LEAFFACES = 16, + + /// + /// Index to brushes in each leaf + /// + LUMP_LEAFBRUSHES = 17, + + /// + /// Brush array + /// + LUMP_BRUSHES = 18, + + /// + /// Brushside array + /// + LUMP_BRUSHSIDES = 19, + + /// + /// Area array + /// + LUMP_AREAS = 20, + + /// + /// Portals between areas + /// + LUMP_AREAPORTALS = 21, + + /// Source 2004 + LUMP_PORTALS = 22, + + /// + /// Unused + /// + /// Source 2007/2009 + LUMP_UNUSED0 = 22, + + /// + /// Static props convex hull lists + /// + /// Source (L4D2 Branch) + LUMP_PROPCOLLISION = 22, + + /// + /// Leaves that are enterable by the player + /// + /// Source 2004 + LUMP_CLUSTERS = 23, + + /// + /// Unused + /// + /// Source 2007/2009 + LUMP_UNUSED1 = 23, + + /// + /// Static prop convex hulls + /// + /// Source (L4D2 Branch) + LUMP_PROPHULLS = 23, + + /// + /// Vertices of portal polygons + /// + /// Source 2004 + LUMP_PORTALVERTS = 24, + + /// + /// Unused + /// + /// Source 2007/2009 + LUMP_UNUSED2 = 24, + + /// + /// Used to store client side entities (Similar to Lump #0) + /// + /// Source (TacInt branch) + LUMP_FAKEENTITIES = 24, + + /// + /// Static prop collision vertices + /// + /// Source (L4D2 Branch) + LUMP_PROPHULLVERTS = 24, + + /// Source 2004 + LUMP_CLUSTERPORTALS = 25, + + /// + /// Unused + /// + /// Source 2007/2009 + LUMP_UNUSED3 = 25, + + /// + /// Static prop per hull triangle index start/count + /// + /// Source (L4D2 Branch) + LUMP_PROPTRIS = 25, + + /// + /// Displacement surface array + /// + LUMP_DISPINFO = 26, + + /// + /// Brush faces array before splitting + /// + LUMP_ORIGINALFACES = 27, + + /// + /// Displacement physics collision data + /// + LUMP_PHYSDISP = 28, + + /// + /// Physics collision data + /// + LUMP_PHYSCOLLIDE = 29, + + /// + /// Face plane normals + /// + LUMP_VERTNORMALS = 30, + + /// + /// Face plane normal index array + /// + LUMP_VERTNORMALINDICES = 31, + + /// + /// Displacement lightmap alphas (unused/empty since Source 2006) + /// + LUMP_DISP_LIGHTMAP_ALPHAS = 32, + + /// + /// Vertices of displacement surface meshes + /// + LUMP_DISP_VERTS = 33, + + /// + /// Displacement lightmap sample positions + /// + LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS = 34, + + /// + /// Game-specific data lump + /// + LUMP_GAME_LUMP = 35, + + /// + /// Data for leaf nodes that are inside water + /// + LUMP_LEAFWATERDATA = 36, + + /// + /// Water polygon data + /// + LUMP_PRIMITIVES = 37, + + /// + /// Water polygon vertices + /// + LUMP_PRIMVERTS = 38, + + /// + /// Water polygon vertex index array + /// + LUMP_PRIMINDICES = 39, + + /// + /// Embedded uncompressed or LZMA-compressed Zip-format file + /// + LUMP_PAKFILE = 40, + + /// + /// Clipped portal polygon vertices + /// + LUMP_CLIPPORTALVERTS = 41, + + /// + /// env_cubemap location array + /// + LUMP_CUBEMAPS = 42, + + /// + /// Texture name data + /// + LUMP_TEXDATA_STRING_DATA = 43, + + /// + /// Index array into texdata string data + /// + LUMP_TEXDATA_STRING_TABLE = 44, + + /// + /// info_overlay data array + /// + LUMP_OVERLAYS = 45, + + /// + /// Distance from leaves to water + /// + LUMP_LEAFMINDISTTOWATER = 46, + + /// + /// Macro texture info for faces + /// + LUMP_FACE_MACRO_TEXTURE_INFO = 47, + + /// + /// Displacement surface triangles + /// + LUMP_DISP_TRIS = 48, + + /// + /// Compressed win32-specific Havok terrain surface collision data. + /// Deprecated and no longer used. + /// + /// Source 2004 + LUMP_PHYSCOLLIDESURFACE = 49, + + /// + /// Static prop triangle and string data + /// + /// Source (L4D2 Branch) + LUMP_PROP_BLOB = 49, + + /// + /// Tied to any entity that uses the overlay_transition helper in FGD + /// + LUMP_WATEROVERLAYS = 50, + + /// + /// Alternate lightdata implementation for Xbox + /// + /// Source 2006 + LUMP_LIGHTMAPPAGES = 51, + + /// + /// Index of LUMP_LEAF_AMBIENT_LIGHTING_HDR + /// + /// Source 2007/2009 + LUMP_LEAF_AMBIENT_INDEX_HDR = 51, + + /// + /// Alternate lightdata indices for Xbox + /// + /// Source 2006 + LUMP_LIGHTMAPPAGEINFOS = 52, + + /// + /// Index of LUMP_LEAF_AMBIENT_LIGHTING + /// + /// Source 2007/2009 + LUMP_LEAF_AMBIENT_INDEX = 52, + + /// + /// HDR lightmap samples + /// + LUMP_LIGHTING_HDR = 53, + + /// + /// Internal HDR world lights converted from the entity lump + /// + LUMP_WORLDLIGHTS_HDR = 54, + + /// + /// Per-leaf ambient light samples (HDR) + /// + LUMP_LEAF_AMBIENT_LIGHTING_HDR = 55, + + /// + /// Per-leaf ambient light samples (LDR) + /// + LUMP_LEAF_AMBIENT_LIGHTING = 56, + + /// + /// XZip version of pak file for Xbox. Deprecated. + /// + LUMP_XZIPPAKFILE = 57, + + /// + /// HDR maps may have different face data + /// + LUMP_FACES_HDR = 58, + + /// + /// Extended level-wide flags. Not present in all levels. + /// + LUMP_MAP_FLAGS = 59, + + /// + /// Fade distances for overlays + /// + LUMP_OVERLAY_FADES = 60, + + /// + /// System level settings (min/max CPU & GPU to render this overlay) + /// + LUMP_OVERLAY_SYSTEM_LEVELS = 61, + + /// + /// PhysX model of the World Brush. + /// + LUMP_PHYSLEVEL = 62, + + /// + /// Displacement multiblend info + /// + LUMP_DISP_MULTIBLEND = 63, + + #endregion + } + + /// + public enum PlaneType : int + { + // Plane is perpendicular to given axis + PLANE_X = 0, + PLANE_Y = 1, + PLANE_Z = 2, + + // Non-axial plane is snapped to the nearest + PLANE_ANYX = 3, + PLANE_ANYY = 4, + PLANE_ANYZ = 5, + } + + /// + [Flags] + public enum StaticPropFlags : uint + { + /// + /// Set by engine at runtime if the model fades out at a distance. + /// + STATIC_PROP_FLAG_FADES = 0x01, + + /// + /// Set by engine at runtime if the model's lighting origin is + /// different from its position in the world. + /// + STATIC_PROP_USE_LIGHTING_ORIGIN = 0x02, + + /// + /// Computed at run time based on dx level + /// + STATIC_PROP_NO_DRAW = 0x04, + + /// + /// Set if disableflashlight is enabled. + /// + STATIC_PROP_NO_FLASHLIGHT = 0x04, + + /// + /// Set if ignorenormals is enabled. + /// + STATIC_PROP_IGNORE_NORMALS = 0x08, + + /// + /// Set if disableshadows is enabled. + /// + STATIC_PROP_NO_SHADOW = 0x10, + + /// + /// Set if disableshadows is enabled. + /// + STATIC_PROP_SCREEN_SPACE_FADE = 0x20, + + /// + /// Set if drawinfastreflection is enabled. + /// + STATIC_PROP_MARKED_FOR_FAST_REFLECTION = 0x20, + + /// + /// In vrad, compute lighting at lighting origin, + /// not for each vertex + /// + STATIC_PROP_NO_PER_VERTEX_LIGHTING = 0x40, + + /// + /// Disable self shadowing in vrad + /// + STATIC_PROP_NO_SELF_SHADOWING = 0x80, + + /// + /// Whether we should do per-texel lightmaps in vrad + /// + STATIC_PROP_NO_PER_TEXEL_LIGHTING = 0x100, + } + + /// + [Flags] + public enum StaticPropFlagsEx : uint + { + /// + /// Set if disableshadowdepth is enabled. + /// + STATIC_PROP_FLAGS_EX_DISABLE_SHADOW_DEPTH = 0x00000001, + + /// + /// Automatically set at runtime + /// + STATIC_PROP_FLAGS_EX_DISABLE_CSM = 0x00000002, + + /// + /// Set if enablelightbounce is enabled. + /// + STATIC_PROP_FLAGS_EX_ENABLE_LIGHT_BOUNCE = 0x00000004, + } + + /// + [Flags] + public enum SurfaceFlag : uint + { + /// + /// Normally set on any surface that matches a RAD file entry; + /// not actually written to the BSP, unlike Quake II. + /// + SURF_LIGHT = 0x0001, + + /// + /// Deprecated: Legacy Quake II flag; deprecated in favor of + /// surface properties. + /// + SURF_SLICK = 0x0002, + + /// + /// Shows only the 2D skybox. Set via $Compile2DSky + /// + SURF_SKY2D = 0x0002, + + /// + /// Shows both the 2D and 3D skybox. Set via $CompileSky + /// + SURF_SKY = 0x0004, + + /// + /// Tells VVIS and the engine renderer that the surface is water. + /// Set via %CompileWater, but not %CompileSlime. + /// + SURF_WARP = 0x0008, + + /// + /// Surface is translucent, either via $translucent or $alpha. + /// + SURF_TRANS = 0x0010, + + /// + /// Deprecated: Legacy Quake II flag; deprecated in favor of + /// surface properties. + /// + SURF_WET = 0x0020, + + /// + /// Set via %NoPortal + /// + SURF_NOPORTAL = 0x0020, + + /// + /// Deprecated: Legacy Quake II flag; deprecated in favor of + /// material proxies. + /// + SURF_FLOWING = 0x0040, + + /// + /// Set via %CompileTrigger. Doesn't do anything in the PC versions. + /// + SURF_TRIGGER = 0x0040, + + /// + /// Set via %CompileNoDraw + /// + SURF_NODRAW = 0x0080, + + /// + /// Set via %CompileHint + /// + SURF_HINT = 0x0100, + + /// + /// Set via %CompileSkip. Should never be used on anything except + /// a hint brush. + /// + SURF_SKIP = 0x0200, + + /// + /// Don't calculate light + /// + SURF_NOLIGHT = 0x0400, + + /// + /// Calculate three lightmaps for the surface for bumpmapping + /// + SURF_BUMPLIGHT = 0x0800, + + /// + /// Don't receive shadows + /// + SURF_NOSHADOWS = 0x1000, + + /// + /// Don't receive decals + /// + SURF_NODECALS = 0x2000, + + /// + /// Don't subdivide patches on this surface + /// + SURF_NOCHOP = 0x4000, + + /// + /// Surface is part of a hitbox + /// + SURF_HITBOX = 0x8000, + } + + /// + [Flags] + public enum TextureFlag : uint + { + /// + /// Disable lightmaps and subdivision for the surface + /// + /// Used by sky and liquids + DisableLightmaps = 0x01, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/GameLump.cs b/SabreTools.Serialization/Models/BSP/GameLump.cs new file mode 100644 index 00000000..1fc4bd6e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/GameLump.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The Game lump (Lump 35) seems to be intended to be used for + /// map data that is specific to a particular game using the Source + /// engine, so that the file format can be extended without altering + /// the previously defined format. + /// + /// + public sealed class GameLump + { + /// + /// Number of game lumps + /// + public int LumpCount; + + /// + /// + /// + public GameLumpDirectory[]? Directories; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/GameLumpDirectory.cs b/SabreTools.Serialization/Models/BSP/GameLumpDirectory.cs new file mode 100644 index 00000000..7a1a3826 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/GameLumpDirectory.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The Game lump (Lump 35) seems to be intended to be used for + /// map data that is specific to a particular game using the Source + /// engine, so that the file format can be extended without altering + /// the previously defined format. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class GameLumpDirectory + { + /// + /// Gamelump ID + /// + public int Id; + + /// + /// Flags + /// + public ushort Flags; + + /// + /// Gamelump version + /// + public ushort Version; + + /// + /// Offset to this gamelump + /// + public int FileOffset; + + /// + /// Length + /// + public int FileLength; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LeafAmbientIndex.cs b/SabreTools.Serialization/Models/BSP/LeafAmbientIndex.cs new file mode 100644 index 00000000..9c5b97f2 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LeafAmbientIndex.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// To associate each leaf with its collection of ambient samples, + /// the ambient lighting index lumps (Lumps 51 and 52) are used. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class LeafAmbientIndex + { + public ushort AmbientSampleCount; + + public ushort FirstAmbientSample; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LeafAmbientLighting.cs b/SabreTools.Serialization/Models/BSP/LeafAmbientLighting.cs new file mode 100644 index 00000000..d1916825 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LeafAmbientLighting.cs @@ -0,0 +1,41 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The ambient lighting lumps (Lumps 55 and 56) are present in + /// BSP version 20 and later. Lump 55 is used for HDR lighting, + /// and Lump 56 is used for LDR lighting. These lumps are used to + /// store the volumetric ambient lighting information in each leaf + /// (i.e. lighting information for entities such as NPCs, the + /// viewmodel, and non-static props). Prior to version 20, this + /// data was stored in the leaf lump (Lump 10), in the dleaf_t + /// structure, with far less precision than this newer lump allows. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class LeafAmbientLighting + { + public CompressedLightCube? Cube; + + /// + /// Fixed point fraction of leaf bounds + /// + public byte X; + + /// + /// Fixed point fraction of leaf bounds + /// + public byte Y; + + /// + /// Fixed point fraction of leaf bounds + /// + public byte Z; + + /// + /// Unused + /// + public byte Pad; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LeafBrushesLump.cs b/SabreTools.Serialization/Models/BSP/LeafBrushesLump.cs new file mode 100644 index 00000000..000e93fc --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LeafBrushesLump.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The leafbrush lump (Lump 17) is an array of unsigned shorts which are + /// used to map from brushes referenced in the leaf structure to indices in + /// the brush array. + /// + /// + public sealed class LeafBrushesLump : Lump + { + /// + /// Map + /// + public ushort[]? Map { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LeafFacesLump.cs b/SabreTools.Serialization/Models/BSP/LeafFacesLump.cs new file mode 100644 index 00000000..33021f6c --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LeafFacesLump.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The leafface lump (Lump 16) is an array of unsigned shorts which are + /// used to map from faces referenced in the leaf structure to indices in + /// the face array. + /// + /// + public sealed class LeafFacesLump : Lump + { + /// + /// Map + /// + public ushort[]? Map { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LightmapLump.cs b/SabreTools.Serialization/Models/BSP/LightmapLump.cs new file mode 100644 index 00000000..f7024939 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LightmapLump.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This is one of the largest lumps in the BSP file. The lightmap + /// lump stores all lightmaps used in the entire map. The lightmaps + /// are arrays of triples of bytes (3 channel color, RGB) and stored + /// continuously. + /// + /// + public sealed class LightmapLump : Lump + { + /// + /// Lightmap RGB values + /// + /// Array of 3-byte values + public byte[][]? Lightmap { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Lump.cs b/SabreTools.Serialization/Models/BSP/Lump.cs new file mode 100644 index 00000000..5615b228 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Lump.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Represents a common Lump type + /// + /// + /// + public abstract class Lump + { + // No shared fields between types + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/LzmaHeader.cs b/SabreTools.Serialization/Models/BSP/LzmaHeader.cs new file mode 100644 index 00000000..53a4950e --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/LzmaHeader.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// BSP files for console platforms such as PlayStation 3 and + /// Xbox 360 usually have their lumps compressed with LZMA. + /// In this case, the lump data starts with the following header + /// (from public/tier1/lzmaDecoder.h), which is used in place of + /// the standard 13-byte LZMA header. + /// + /// lzmaSize denotes the size (in bytes) of compressed data, it + /// is equal to the size of a lump minus 17 bytes (lzma header). + /// actualSize denotes the size of decompressed data. properties[5] + /// field are used solely for LZMA decoding. + /// + /// There are two special cases for compression: LUMP_PAKFILE is never + /// compressed as a lump (the contents of the zip are compressed instead) + /// and each of the game lumps in LUMP_GAME_LUMP are compressed individually. + /// The compressed size of a game lump can be determined by subtracting + /// the current game lump's offset with that of the next entry. For this + /// reason, when game lumps are compressed the last game lump is always + /// an empty dummy which only contains the offset. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class LzmaHeader + { + public uint Id; + + /// Little-endian + public uint ActualSize; + + /// Little-endian + public uint LzmaSize; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[]? Properties = new byte[5]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/MarksurfacesLump.cs b/SabreTools.Serialization/Models/BSP/MarksurfacesLump.cs new file mode 100644 index 00000000..441bcdf1 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/MarksurfacesLump.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The marksurfaces lump is a simple array of short integers. + /// + /// This lump is a simple table for redirecting the marksurfaces + /// indexes in the leafs to the actial face indexes. A leaf inserts + /// it's marksurface indexes into this array and gets the associated + /// faces contained within this leaf. + /// + /// + public sealed class MarksurfacesLump : Lump + { + /// + /// Marksurfaces + /// + public ushort[]? Marksurfaces { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/MipTexture.cs b/SabreTools.Serialization/Models/BSP/MipTexture.cs new file mode 100644 index 00000000..e3e30a80 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/MipTexture.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Each of this structs describes a texture. The name of the + /// texture is a string and may be 16 characters long (including + /// the null-character at the end, char equals a 8bit signed + /// integer). The name of the texture is needed, if the texture + /// has to be found and loaded from an external WAD file. + /// Furthermore, the struct contains the width and height of + /// the texture. The 4 offsets at the end can either be zero, + /// if the texture is stored in an external WAD file, or point + /// to the beginnings of the binary texture data within the + /// texture lump relative to the beginning of it's BSPMIPTEX struct. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class MipTexture + { + /// + /// Name of texture + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.MAXTEXTURENAME)] + public string? Name; + + /// + /// Extends of the texture + /// + public uint Width; + + /// + /// Extends of the texture + /// + public uint Height; + + /// + /// Offsets to texture mipmaps BSPMIPTEX + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.MIPLEVELS)] + public uint[]? Offsets; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/OccluderData.cs b/SabreTools.Serialization/Models/BSP/OccluderData.cs new file mode 100644 index 00000000..c5c3e71f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/OccluderData.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The doccluderdata_t structure contains flags and dimensions + /// of the occluder, as well as the area where it remains. + /// firstpoly is the first index into the doccluderpolydata_t + /// with a total of polycount entries. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class OccluderData + { + public int Flags; + + /// + /// Index into doccluderpolys + /// + public int FirstPoly; + + /// + /// Amount of polygons + /// + public int PolyCount; + + /// + /// Minima of all vertices + /// + public Vector3D? Mins; + + /// + /// Maxima of all vertices + /// + public Vector3D? Maxs; + + /// Since v1 + public int Area; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/OccluderPolyData.cs b/SabreTools.Serialization/Models/BSP/OccluderPolyData.cs new file mode 100644 index 00000000..eb60a787 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/OccluderPolyData.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Occluder polygons are stored in the doccluderpolydata_t + /// structure and contain the firstvertexindex field, which + /// is the first index into the vertex array of the occluder, + /// which are again indices for the vertex array of the vertex + /// lump (Lump 3). The total number of vertex indices is + /// stored in vertexcount. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class OccluderPolyData + { + /// + /// Index into doccludervertindices + /// + public int FirstVertexIndex; + + /// + /// Amount of vertex indices + /// + public int VertexCount; + + public int PlanEnum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/OcclusionLump.cs b/SabreTools.Serialization/Models/BSP/OcclusionLump.cs new file mode 100644 index 00000000..52eda612 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/OcclusionLump.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The occlusion lump (Lump 9) contains the polygon geometry and some + /// flags used by func_occluder entities. Unlike other brush entities, + /// func_occluders don't use the 'model' key in the entity lump. + /// Instead, the brushes are split from the entities during the compile + /// process and numeric occluder keys are assigned as 'occludernum'. + /// Brush sides textured with tools/toolsoccluder or tools/toolstrigger + /// are then stored together with the occluder keys and some additional + /// info in this lump. + /// + /// The lump is divided into three parts and begins with a integer value + /// with the total number of occluders, followed by an array of + /// doccluderdata_t fields of the same size. The next part begins with + /// another integer value, this time for the total number of occluder + /// polygons, as well as an array of doccluderpolydata_t fields of equal + /// size. Part three begins with another integer value for the amount of + /// occluder polygon vertices, followed by an array of integer values for + /// the vertex indices, again of the same size. + /// + /// + public sealed class OcclusionLump : Lump + { + public int Count; + + /// + /// + /// + public OccluderData[]? Data; + + public int PolyDataCount; + + /// + /// + /// + public OccluderPolyData[]? PolyData; + + public int VertexIndexCount; + + /// + /// + /// + public int[]? VertexIndicies; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Overlay.cs b/SabreTools.Serialization/Models/BSP/Overlay.cs new file mode 100644 index 00000000..98b1f47b --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Overlay.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Unlike the simpler decals (infodecal entities), info_overlays + /// are removed from the entity lump and stored separately in the + /// Overlay lump (Lump 45). + /// + /// The FaceCountAndRenderOrder member is split into two parts; + /// the lower 14 bits are the number of faces that the overlay + /// appears on, with the top 2 bits being the render order of + /// the overlay (for overlapping decals). The Ofaces array, which + /// is 64 elements in size (OVERLAY_BSP_FACE_COUNT) are the indices + /// into the face array indicating which map faces the overlay + /// should be displayed on. The other elements set the texture, + /// scale, and orientation of the overlay decal. There is no + /// enforced limit on overlays inside the engine. VBSP enforces + /// a limit of 512 (MAX_MAP_OVERLAYS, 1024 in Counter-Strike: + /// Global Offensive), but custom compilers can circumvent this. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Overlay + { + public int Id; + + public short TexInfo; + + public ushort FaceCountAndRenderOrder; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.OVERLAY_BSP_FACE_COUNT)] + public int[]? Ofaces = new int[Constants.OVERLAY_BSP_FACE_COUNT]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public float[]? U = new float[2]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public float[]? V = new float[2]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public Vector3D[]? UVPoints = new Vector3D[4]; + + public Vector3D? Origin; + + public Vector3D? BasisNormal; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/OverlaysLump.cs b/SabreTools.Serialization/Models/BSP/OverlaysLump.cs new file mode 100644 index 00000000..638a3718 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/OverlaysLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class OverlaysLump : Lump + { + /// + /// Overlays + /// + public Overlay[]? Overlays { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/PakfileLump.cs b/SabreTools.Serialization/Models/BSP/PakfileLump.cs new file mode 100644 index 00000000..59ae0efd --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/PakfileLump.cs @@ -0,0 +1,43 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The Pakfile lump (Lump 40) is a special lump that can contains + /// multiple files which are embedded into the bsp file. Usually, + /// they contain special texture (.vtf) and material (.vmt) files + /// which are used to store the reflection maps from env_cubemap + /// entities in the map; these files are built and placed in the + /// Pakfile lump when the buildcubemaps console command is executed. + /// The Pakfile can optionally contain such things as custom textures + /// and prop models used in the map, and are placed into the bsp file + /// by using the BSPZIP program (or alternate programs such as Pakrat). + /// These files are integrated into the game engine's file system + /// and will be loaded preferentially before externally located + /// files are used. + /// + /// The format of the Pakfile lump is identical to that used by the + /// Zip compression utility when no compression is specified (i.e., + /// the individual files are stored in uncompressed format). In some + /// branches, such as , LZMA compression can be used as well. If the + /// Pakfile lump is extracted and written to a file, it can therefore + /// be opened with WinZip and similar programs. + /// + /// The header public/zip_uncompressed.h defines the structures + /// present in the Pakfile lump. The last element in the lump is a + /// ZIP_EndOfCentralDirRecord structure. This points to an array of + /// ZIP_FileHeader structures immediately preceeding it, one for each + /// file present in the Pak. Each of these headers then point to + /// ZIP_LocalFileHeader structures that are followed by that file's + /// data. + /// + /// The Pakfile lump is usually the last element of the bsp file. + /// + /// + public sealed class PakfileLump + { + /// + /// Pakfile data + /// + /// TODO: Split and/or decompress data? + public byte[]? Data; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/PhysCollideLump.cs b/SabreTools.Serialization/Models/BSP/PhysCollideLump.cs new file mode 100644 index 00000000..1a4663c0 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/PhysCollideLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class PhysCollideLump : Lump + { + /// + /// Models + /// + public PhysModel[]? Models { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/PhysModel.cs b/SabreTools.Serialization/Models/BSP/PhysModel.cs new file mode 100644 index 00000000..c8d0c6b4 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/PhysModel.cs @@ -0,0 +1,42 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The physcollide lump (Lump 29) contains physics data for the world. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class PhysModel + { + /// + /// Perhaps the index of the model to which this physics model applies? + /// + public int ModelIndex; + + /// + /// Total size of the collision data sections + /// + public int DataSize; + + /// + /// Size of the text section + /// + public int KeydataSize; + + /// + /// Number of collision data sections + /// + public int SolidCount; + + /// + /// Collision data of length + /// + public PhysSolid[]? Solids; + + /// + /// Key data of size + /// + public byte[]? TextData; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/PhysSolid.cs b/SabreTools.Serialization/Models/BSP/PhysSolid.cs new file mode 100644 index 00000000..d86f3f92 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/PhysSolid.cs @@ -0,0 +1,25 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The last two parts appear to be identical to the PHY file format, + /// which means their exact contents are unknown. Note that the + /// compactsurfaceheader_t structure contains the data size of each + /// collision data section (including the rest of the header) + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class PhysSolid + { + /// + /// Size of the collision data + /// + public int Size; + + /// + /// Collision data of length + /// + public byte[]? CollisionData; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Plane.cs b/SabreTools.Serialization/Models/BSP/Plane.cs new file mode 100644 index 00000000..4d3ba78f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Plane.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Each of this structures defines a plane in 3-dimensional + /// space by using the Hesse normal form: normal * point - distance = 0 + /// + /// Where vNormal is the normalized normal vector of the plane + /// and fDist is the distance of the plane to the origin of + /// the coord system. Additionally, the structure also saves an + /// integer describing the orientation of the plane in space. + /// If nType equals PLANE_X, then the normal of the plane will + /// be parallel to the x axis, meaning the plane is perpendicular + /// to the x axis. If nType equals PLANE_ANYX, then the plane's + /// normal is nearer to the x axis then to any other axis. + /// This information is used by the renderer to speed up some + /// computations. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Plane + { + /// + /// The planes normal vector + /// + public Vector3D? NormalVector; + + /// + /// Plane equation is: vNormal * X = fDist + /// + public float Distance; + + /// + /// Plane type + /// + public PlaneType PlaneType; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/PlanesLump.cs b/SabreTools.Serialization/Models/BSP/PlanesLump.cs new file mode 100644 index 00000000..37757d46 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/PlanesLump.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + public sealed class PlanesLump : Lump + { + /// + /// Planes + /// + public Plane[]? Planes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/QAngle.cs b/SabreTools.Serialization/Models/BSP/QAngle.cs new file mode 100644 index 00000000..c7356b64 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/QAngle.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// QAngle is a C++ class in Source that represents a three-dimensional + /// extrinsic Tait-Bryan rotations following the right-hand rule, offset + /// from the cardinal Z axis. + /// + [StructLayout(LayoutKind.Sequential)] + public class QAngle + { + public float X; + public float Y; + public float Z; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/StaticPropDictLump.cs b/SabreTools.Serialization/Models/BSP/StaticPropDictLump.cs new file mode 100644 index 00000000..f1439a8f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/StaticPropDictLump.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Of interest is the gamelump which is used to store prop_static entities, + /// which uses the gamelump ID of 'sprp' ASCII (1936749168 decimal). Unlike + /// most other entities, static props are not stored in the entity lump. The + /// gamelump formats used in Source are defined in the public/gamebspfile.h + /// header file. + /// + /// The first element of the static prop game lump is the dictionary; this is + /// an integer count followed by the list of model (prop) names used in the map + /// + /// + public sealed class StaticPropDictLump + { + public int DictEntries; + + /// + /// Model name + /// + /// [dictEntries][128] + public char[][]? Name; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/StaticPropLeafLump.cs b/SabreTools.Serialization/Models/BSP/StaticPropLeafLump.cs new file mode 100644 index 00000000..e07f3b16 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/StaticPropLeafLump.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Presumably, this array is used to index into the leaf lump + /// to locate the leaves that each prop static is located in. + /// Note that a prop static may span several leaves. + /// + /// + public sealed class StaticPropLeafLump + { + public int LeafEntries; + + /// + /// + /// + public ushort[]? Leaf; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/StaticPropLump.cs b/SabreTools.Serialization/Models/BSP/StaticPropLump.cs new file mode 100644 index 00000000..17a2845a --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/StaticPropLump.cs @@ -0,0 +1,185 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The coordinates of the prop are given by the Origin member; its + /// orientation (pitch, yaw, roll) is given by the Angles entry, which + /// is a 3-float vector. The PropType element is an index into the + /// dictionary of prop model names, given above. The other elements + /// correspond to the location of the prop in the BSP structure of the + /// map, its lighting, and other entity properties as set in Hammer. + /// The other elements (ForcedFadeScale, etc.) are only present in the + /// static prop structure if the gamelump's specified version is high enough + /// (see dgamelump_t.version); both version 4 and version 5 static prop + /// gamelumps are used in official Half-Life 2 maps. Version 6 has been + /// encountered in Team Fortress 2; Version 7 is used in some Left 4 Dead + /// maps, and a modified version 7 is present in Zeno Clash maps. Version 8 + /// is used predominantly in Left 4 Dead, and version 9 in Left 4 Dead 2. + /// The new version 10 appears in Tactical Intervention. Version 11 is used in + /// Counter-Strike: Global Offensive since the addition of uniform prop scaling + /// (before this it was version 10). After version 7, DX level options were + /// removed. In version 11 XBox 360 flags were removed. + /// + /// Version 7* is used by games built on Source 2013 Multiplayer + /// ( Team Fortress 2, Counter-Strike: Source, etc.) and may come across as + /// either version 7 or 10. Specifically, Team Fortress 2 has referred to it + /// as version 7 in the past but now refers to it as version 10 even though + /// they are identical. This version's structure is based on version 6 but + /// rearranged such that Flags is an int and at the bottom, above two new + /// entries. These new entries (LightmapResX and LightmapResY) control the + /// width and height of the prop's lightmap image and are specific to this + /// version. + /// + /// + public sealed class StaticPropLump + { + #region v4 + + /// + /// Origin + /// + public Vector3D? Origin; + + /// + /// Orientation (pitch yaw roll) + /// + public QAngle? Angles; + + #endregion + + #region v4 + + /// + /// Index into model name dictionary + /// + public ushort PropType; + + /// + /// Index into leaf array + /// + public ushort FirstLeaf; + + public ushort LeafCount; + + /// + /// Solidity type + /// + public byte Solid; + + #endregion + + #region Every version except v7* + + [MarshalAs(UnmanagedType.U1)] + public StaticPropFlags FlagsV4; + + #endregion + + #region v4 still + + /// + /// Model skin numbers + /// + public int Skin; + + public float FadeMinDist; + + public float FadeMaxDist; + + /// + /// For lighting + /// + public Vector3D? LightingOrigin; + + #endregion + + #region Since v5 + + /// + /// Fade distance scale + /// + public float ForcedFadeScale; + + #endregion + + #region v6, v7, and v7* only + + /// + /// Minimum DirectX version to be visible + /// + public ushort MinDXLevel; + + /// + /// Maximum DirectX version to be visible + /// + public ushort MaxDXLevel; + + #endregion + + #region v7* only + + [MarshalAs(UnmanagedType.U4)] + public byte FlagsV7; + + /// + /// Lightmap image width + /// + public ushort LightmapResX; + + /// + /// Lightmap image height + /// + public ushort LightmapResY; + + #endregion + + #region Since v8 + + public byte MinCPULevel; + + public byte MaxCPULevel; + + public byte MinGPULevel; + + public byte MaxGPULevel; + + #endregion + + #region Since v7 + + /// + /// Per instance color and alpha modulation + /// + public ColorRGBExp32? DiffuseModulation; + + #endregion + + #region v9 and v10 only + + /// + /// If true, don't show on XBox 360 (4-bytes long) + /// + public bool DisableX360; + + #endregion + + #region Since v10 + + /// + /// Further bitflags. + /// + public StaticPropFlagsEx FlagsEx; + + #endregion + + #region Since v11 + + /// + /// Prop scale + /// + public float UniformScale; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/SurfedgesLump.cs b/SabreTools.Serialization/Models/BSP/SurfedgesLump.cs new file mode 100644 index 00000000..fb23170f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/SurfedgesLump.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This lump represents pretty much the same mechanism as the marksurfaces. + /// A face can insert its surfedge indexes into this array to get the + /// corresponding edges delimitting the face and further pointing to the + /// vertexes, which are required for rendering. The index can be positive + /// or negative. If the value of the surfedge is positive, the first vertex + /// of the edge is used as vertex for rendering the face, otherwise, the + /// value is multiplied by -1 and the second vertex of the indexed edge is + /// used. + /// + /// + /// + public sealed class SurfedgesLump : Lump + { + /// + /// Surfedges + /// + public int[]? Surfedges { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Texdata.cs b/SabreTools.Serialization/Models/BSP/Texdata.cs new file mode 100644 index 00000000..79b4543d --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Texdata.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The reflectivity vector corresponds to the RGB components of the reflectivity + /// of the texture, as derived from the material's .vtf file. This is probably + /// used in radiosity (lighting) calculations of what light bounces from the + /// texture's surface. The nameStringTableID is an index into the TexdataStringTable + /// array (below). The other members relate to the texture's source image. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Texdata + { + /// + /// RGB reflectivity + /// + public Vector3D? Reflectivity; + + /// + /// Index into TexdataStringTable + /// + public int NameStringTableID; + + /// + /// Source image + /// + public int Width; + + /// + /// Source image + /// + public int Height; + + public int ViewWidth; + + public int ViewHeight; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/TexdataLump.cs b/SabreTools.Serialization/Models/BSP/TexdataLump.cs new file mode 100644 index 00000000..631e3ded --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/TexdataLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class TexdataLump : Lump + { + /// + /// Texdatas + /// + public Texdata[]? Texdatas { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/TexdataStringData.cs b/SabreTools.Serialization/Models/BSP/TexdataStringData.cs new file mode 100644 index 00000000..f07f4e5c --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/TexdataStringData.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The TexdataStringData lump consists of concatenated null-terminated + /// strings giving the texture name. + /// + /// + public sealed class TexdataStringData : Lump + { + /// + /// Strings + /// + public string[]? Strings { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/TexdataStringTable.cs b/SabreTools.Serialization/Models/BSP/TexdataStringTable.cs new file mode 100644 index 00000000..befb27f0 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/TexdataStringTable.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The TexdataStringTable (Lump 44) is an array of integers which + /// are offsets into the TexdataStringData (lump 43). + /// + /// + public sealed class TexdataStringTable : Lump + { + /// + /// Offsets + /// + public int[]? Offsets { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/TextureHeader.cs b/SabreTools.Serialization/Models/BSP/TextureHeader.cs new file mode 100644 index 00000000..1bf89e83 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/TextureHeader.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + public sealed class TextureHeader + { + /// + /// Number of BSPMIPTEX structures + /// + public uint MipTextureCount { get; set; } + + /// + /// Offsets + /// + /// entries + public int[]? Offsets { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/TextureLump.cs b/SabreTools.Serialization/Models/BSP/TextureLump.cs new file mode 100644 index 00000000..ba6cacb3 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/TextureLump.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class TextureLump : Lump + { + /// + /// Texture header data + /// + public TextureHeader? Header { get; set; } + + /// + /// Textures + /// + public MipTexture[]? Textures { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspFace.cs b/SabreTools.Serialization/Models/BSP/VbspFace.cs new file mode 100644 index 00000000..00922559 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspFace.cs @@ -0,0 +1,105 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The face lump (Lump 7) contains the major geometry of the map, + /// used by the game engine to render the viewpoint of the player. + /// The face lump contains faces after they have undergone the BSP + /// splitting process; they therefore do not directly correspond to + /// the faces of brushes created in Hammer. Faces are always flat, + /// convex polygons, though they can contain edges that are co-linear. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class VbspFace + { + /// + /// The plane number + /// + public ushort PlaneNum; + + /// + /// Faces opposite to the node's plane direction + /// + public byte Side; + + /// + /// of on node, 0 if in leaf + /// + public byte OnNode; + + /// + /// Index of the first surfedge + /// + public int FirstEdgeIndex; + + /// + /// Number of consecutive surfedges + /// + public short NumberOfEdges; + + /// + /// Index of the texture info structure + /// + public short TextureInfoIndex; + + /// + /// Index of the displacement info structure + /// + public short DisplacementInfoIndex; + + /// + /// ? + /// + public short SurfaceFogVolumeID; + + /// + /// Switchable lighting info + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[]? Styles = new byte[4]; + + /// + /// Offset into lightmap lump + /// + public int LightmapOffset; + + /// + /// Face area in units^2 + /// + public float Area; + + /// + /// Texture lighting info + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public int[]? LightmapTextureMinsInLuxels = new int[2]; + + /// + /// Texture lighting info + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public int[]? LightmapTextureSizeInLuxels = new int[2]; + + /// + /// Original face this was split from + /// + public int OrigFace; + + /// + /// Primitives + /// + public ushort PrimitiveCount; + + /// + /// First primitive ID + /// + public ushort FirstPrimitiveID; + + /// + /// Lightmap smoothing group + /// + public uint SmoothingGroups; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspFacesLump.cs b/SabreTools.Serialization/Models/BSP/VbspFacesLump.cs new file mode 100644 index 00000000..6a28f13d --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspFacesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class VbspFacesLump : Lump + { + /// + /// Faces + /// + public VbspFace[]? Faces { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspFile.cs b/SabreTools.Serialization/Models/BSP/VbspFile.cs new file mode 100644 index 00000000..5ee4b3cc --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspFile.cs @@ -0,0 +1,367 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// Half-Life Level + /// + /// + /// + public sealed class VbspFile + { + /// + /// Header data + /// + public VbspHeader? Header { get; set; } + + #region Lumps + + /// + /// LUMP_ENTITIES [0] + /// + public EntitiesLump? Entities { get; set; } + + /// + /// LUMP_PLANES [1] + /// + public PlanesLump? PlanesLump { get; set; } + + /// + /// LUMP_TEXDATA [2] + /// + public TexdataLump? TexdataLump { get; set; } + + /// + /// LUMP_VERTEXES [3] + /// + public VerticesLump? VerticesLump { get; set; } + + /// + /// LUMP_VISIBILITY [4] + /// + public VisibilityLump? VisibilityLump { get; set; } + + /// + /// LUMP_NODES [5] + /// + public VbspNodesLump? NodesLump { get; set; } + + /// + /// LUMP_TEXINFO [6] + /// + public VbspTexinfoLump? TexinfoLump { get; set; } + + /// + /// LUMP_FACES [7] + /// + public VbspFacesLump? FacesLump { get; set; } + + /// + /// LUMP_LIGHTING [8] + /// + public LightmapLump? LightmapLump { get; set; } + + /// + /// LUMP_OCCLUSION [9] + /// s + public OcclusionLump? OcclusionLump { get; set; } + + /// + /// LUMP_LEAVES [10] + /// + public VbspLeavesLump? LeavesLump { get; set; } + + /// + /// LUMP_FACEIDS [11] + /// + public MarksurfacesLump? MarksurfacesLump { get; set; } + + /// + /// LUMP_EDGES [12] + /// + public EdgesLump? EdgesLump { get; set; } + + /// + /// LUMP_SURFEDGES [13] + /// + public SurfedgesLump? SurfedgesLump { get; set; } + + /// + /// LUMP_MODELS [14] + /// + public VbspModelsLump? ModelsLump { get; set; } + + /// + /// LUMP_WORLDLIGHTS [15] + /// + public WorldLightsLump? LDRWorldLightsLump { get; set; } + + /// + /// LUMP_LEAFFACES [16] + /// + public LeafFacesLump? LeafFacesLump { get; set; } + + /// + /// LUMP_LEAFBRUSHES [17] + /// + public LeafBrushesLump? LeafBrushesLump { get; set; } + + /// + /// LUMP_BRUSHES [18] + /// + public BrushesLump? BrushesLump { get; set; } + + /// + /// LUMP_BRUSHSIDES [19] + /// + public BrushsidesLump? BrushsidesLump { get; set; } + + /// + /// LUMP_AREAS [20] + /// + /// TODO: Find definition and implement + // public AreasLump? AreasLump { get; set; } + + /// + /// LUMP_AREAPORTALS [21] + /// + /// TODO: Find definition and implement + // public AreaPortalsLump? AreaPortalsLump { get; set; } + + /// + /// LUMP_PORTALS / LUMP_UNUSED0 / LUMP_PROPCOLLISION [22] + /// + /// TODO: Find definition and implement + // public PortalsLump? PortalsLump { get; set; } + + /// + /// LUMP_CLUSTERS / LUMP_UNUSED1 / LUMP_PROPHULLS [23] + /// + /// TODO: Find definition and implement + // public ClustersLump? ClustersLump { get; set; } + + /// + /// LUMP_PORTALVERTS / LUMP_UNUSED2 / LUMP_FAKEENTITIES / LUMP_PROPHULLVERTS [24] + /// + /// TODO: Find definition and implement + // public PortalVertsLump? PortalVertsLump { get; set; } + + /// + /// LUMP_CLUSTERPORTALS / LUMP_UNUSED3 / LUMP_PROPTRIS [25] + /// + /// TODO: Find definition and implement + // public ClusterPortalsLump? ClusterPortalsLump { get; set; } + + /// + /// LUMP_DISPINFO [26] + /// + public DispInfosLump? DispInfosLump { get; set; } + + /// + /// LUMP_ORIGINALFACES [27] + /// + public VbspFacesLump? OriginalFacesLump { get; set; } + + /// + /// LUMP_PHYSDISP [28] + /// + /// TODO: Find definition and implement + // public PhysDispLump? PhysDispLump { get; set; } + + /// + /// LUMP_PHYSCOLLIDE [29] + /// + public PhysCollideLump? PhysCollideLump { get; set; } + + /// + /// LUMP_VERTNORMALS [30] + /// + /// TODO: Find definition and implement + // public VertNormalsLump? VertNormalsLump { get; set; } + + /// + /// LUMP_VERTNORMALINDICES [31] + /// + /// TODO: Find definition and implement + // public VertNormalIndicesLump? VertNormalIndicesLump { get; set; } + + /// + /// LUMP_DISP_LIGHTMAP_ALPHAS [32] + /// + /// TODO: Find definition and implement + // public DispLightmapAlphasLump? DispLightmapAlphasLump { get; set; } + + /// + /// LUMP_DISP_VERTS [33] + /// + public DispVertsLump? DispVertsLump { get; set; } + + /// + /// LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS [34] + /// + /// TODO: Find definition and implement + // public DispLightmapSamplePositions? DispLightmapSamplePositions { get; set; } + + /// + /// LUMP_GAME_LUMP [35] + /// + public GameLump? GameLump { get; set; } + + /// + /// LUMP_LEAFWATERDATA [36] + /// + /// TODO: Find definition and implement + // public LeafWaterDataLump? LeafWaterDataLump { get; set; } + + /// + /// LUMP_PRIMITIVES [37] + /// + /// TODO: Find definition and implement + // public PrimitivesLump? PrimitivesLump { get; set; } + + /// + /// LUMP_PRIMVERTS [38] + /// + /// TODO: Find definition and implement + // public PrimVertsLump? PrimVertsLump { get; set; } + + /// + /// LUMP_PRIMINDICES [39] + /// + /// TODO: Find definition and implement + // public PrimIndicesLump? PrimIndicesLump { get; set; } + + /// + /// LUMP_PAKFILE [40] + /// + public PakfileLump? PakfileLump { get; set; } + + /// + /// LUMP_CLIPPORTALVERTS [41] + /// + /// TODO: Find definition and implement + // public ClipPortalVertsLump? ClipPortalVertsLump { get; set; } + + /// + /// LUMP_CUBEMAPS [42] + /// + public CubemapsLump? CubemapsLump { get; set; } + + /// + /// LUMP_TEXDATA_STRING_DATA [43] + /// + public TexdataStringData? TexdataStringData { get; set; } + + /// + /// LUMP_TEXDATA_STRING_TABLE [44] + /// + public TexdataStringTable? TexdataStringTable { get; set; } + + /// + /// LUMP_OVERLAYS [45] + /// + public OverlaysLump? OverlaysLump { get; set; } + + /// + /// LUMP_LEAFMINDISTTOWATER [46] + /// + /// TODO: Find definition and implement + // public LeafMindIsToWaterLump? LeafMindIsToWaterLump { get; set; } + + /// + /// LUMP_FACE_MACRO_TEXTURE_INFO [47] + /// + /// TODO: Find definition and implement + // public FaceMacroTextureInfoLump? FaceMacroTextureInfoLump { get; set; } + + /// + /// LUMP_DISP_TRIS [48] + /// + public DispTrisLump? DispTrisLump { get; set; } + + /// + /// LUMP_PHYSCOLLIDESURFACE / LUMP_PROP_BLOB [49] + /// + /// TODO: Find definition and implement + // public PhysCollideSurfaceLump? PhysCollideSurfaceLump { get; set; } + + /// + /// LUMP_WATEROVERLAYS [50] + /// + /// TODO: Find definition and implement + // public WaterOverlaysLump? WaterOverlaysLump { get; set; } + + /// + /// LUMP_LIGHTMAPPAGES / LUMP_LEAF_AMBIENT_INDEX_HDR [51] + /// + public AmbientIndexLump? HDRAmbientIndexLump { get; set; } + + /// + /// LUMP_LIGHTMAPPAGEINFOS / LUMP_LEAF_AMBIENT_INDEX [52] + /// + public AmbientIndexLump? LDRAmbientIndexLump { get; set; } + + /// + /// LUMP_LIGHTING_HDR [53] + /// + /// TODO: Find definition and implement + // public LightingHdrLump? LightingHdrLump { get; set; } + + /// + /// LUMP_WORLDLIGHTS_HDR [54] + /// + public WorldLightsLump? HDRWorldLightsLump { get; set; } + + /// + /// LUMP_LEAF_AMBIENT_LIGHTING_HDR [55] + /// + public AmbientLightingLump? HDRAmbientLightingLump { get; set; } + + /// + /// LUMP_LEAF_AMBIENT_LIGHTING [56] + /// + public AmbientLightingLump? LDRAmbientLightingLump { get; set; } + + /// + /// LUMP_XZIPPAKFILE [57] + /// + /// TODO: Find definition and implement + // public XzipPakFileLump? XzipPakFileLump { get; set; } + + /// + /// LUMP_FACES_HDR [58] + /// + /// TODO: Find definition and implement + // public FacesHdrLump? FacesHdrLump { get; set; } + + /// + /// LUMP_MAP_FLAGS [59] + /// + /// TODO: Find definition and implement + // public MapFlagsLump? MapFlagsLump { get; set; } + + /// + /// LUMP_OVERLAY_FADES [60] + /// + /// TODO: Find definition and implement + // public OverlayFadesLump? OverlayFadesLump { get; set; } + + /// + /// LUMP_OVERLAY_SYSTEM_LEVELS [61] + /// + /// TODO: Find definition and implement + // public OverlaySystemLevelsLump? OverlaySystemLevelsLump { get; set; } + + /// + /// LUMP_PHYSLEVEL [62] + /// + /// TODO: Find definition and implement + // public PhysLevelLump? PhysLevelLump { get; set; } + + /// + /// LUMP_DISP_MULTIBLEND [63] + /// + /// TODO: Find definition and implement + // public DispMultiBlendLump? DispMultiBlendLump { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspHeader.cs b/SabreTools.Serialization/Models/BSP/VbspHeader.cs new file mode 100644 index 00000000..553fd5aa --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspHeader.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class VbspHeader + { + /// + /// BSP file signature + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// BSP file version + /// + /// 17,18,19,20,21,22,23,25,27,29 + public int Version; + + /// + /// Lump directory array + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Constants.VBSP_HEADER_LUMPS)] + public VbspLumpEntry[]? Lumps = new VbspLumpEntry[Constants.VBSP_HEADER_LUMPS]; + + /// + /// The map's revision (iteration, version) number. + /// + public int MapRevision; + } +} diff --git a/SabreTools.Serialization/Models/BSP/VbspLeaf.cs b/SabreTools.Serialization/Models/BSP/VbspLeaf.cs new file mode 100644 index 00000000..82319edd --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspLeaf.cs @@ -0,0 +1,99 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The leaves lump contains the leaves of the BSP tree. + /// + /// The first entry of this struct is the type of the content + /// of this leaf. It can be one of the predefined values, found + /// in the compiler source codes, and is litte relevant for the + /// actual rendering process. All the more important is the + /// next integer containing the offset into the vis lump. It + /// defines the start of the raw PVS data for this leaf. If this + /// value equals -1, no VIS lists are available for this leaf, + /// usually if the map has been built without the VIS compiler. + /// The next two 16bit integer triples span the bounding box of + /// this leaf. Furthermore, the struct contains an index pointing + /// into the array of marksurfaces loaded from the marksufaces + /// lump as well as the number of consecutive marksurfaces belonging + /// to this leaf. The marksurfaces are looped through during the + /// rendering process and point to the actual faces. The final 4 bytes + /// specify the volume of ambient sounds in Quake, but are unused in + /// GoldSrc. + /// + /// + public sealed class VbspLeaf + { + /// + /// Contents enumeration + /// + public VbspContents Contents; + + /// + /// Cluster this leaf is in + /// + public short Cluster; + + /// + /// Area this leaf is in and flags + /// + /// area:9, flags:7 + public short AreaFlags; + + /// + /// For frustum culling + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public short[] Mins = new short[3]; + + /// + /// For frustum culling + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public short[] Maxs = new short[3]; + + /// + /// Index into leaffaces + /// + public ushort FirstLeafFace; + + /// + /// Count of leaffaces + /// + public ushort NumLeafFaces; + + /// + /// Index into leafbrushes + /// + public ushort FirstLeafBrush; + + /// + /// Count of leafbrushes + /// + public ushort NumLeafBrushes; + + /// + /// -1 for not in water + /// + public short LeafWaterDataID; + + #region Lump Version 0 + + /// + /// Precaculated light info for entities. + /// + public CompressedLightCube? AmbientLighting; + + #endregion + + #region Lump Version 1+ + + /// + /// Padding to 4-byte boundary + /// + public short Padding; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspLeavesLump.cs b/SabreTools.Serialization/Models/BSP/VbspLeavesLump.cs new file mode 100644 index 00000000..5551ea55 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspLeavesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class VbspLeavesLump : Lump + { + /// + /// Leaves + /// + public VbspLeaf[]? Leaves { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspLumpEntry.cs b/SabreTools.Serialization/Models/BSP/VbspLumpEntry.cs new file mode 100644 index 00000000..415b5223 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspLumpEntry.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class VbspLumpEntry : BspLumpEntry + { + /// + /// Lump format version + /// + public uint Version; + + /// + /// Lump ident code + /// + /// Default to 0, 0, 0, 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[]? FourCC = new byte[4]; + } +} diff --git a/SabreTools.Serialization/Models/BSP/VbspModel.cs b/SabreTools.Serialization/Models/BSP/VbspModel.cs new file mode 100644 index 00000000..68dca38f --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspModel.cs @@ -0,0 +1,45 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// A Model, in the terminology of the BSP file format, is a collection + /// of brushes and faces, often called a "bmodel". It should not be + /// confused with the prop models used in Hammer, which are usually + /// called "studiomodels" in the SDK source. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class VbspModel + { + /// + /// Bounding box + /// + public Vector3D? Mins; + + /// + /// Bounding box + /// + public Vector3D? Maxs; + + /// + /// For sounds or lights + /// + public Vector3D? OriginVector; + + /// + /// Index into nodes + /// + public int HeadNode; + + /// + /// Index into faces + /// + public int FirstFaceIndex; + + /// + /// Count of faces + /// + public int FacesCount; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspModelsLump.cs b/SabreTools.Serialization/Models/BSP/VbspModelsLump.cs new file mode 100644 index 00000000..224e7820 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspModelsLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class VbspModelsLump : Lump + { + /// + /// Model + /// + public VbspModel[]? Models { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspNode.cs b/SabreTools.Serialization/Models/BSP/VbspNode.cs new file mode 100644 index 00000000..18418405 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspNode.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This lump is simple again and contains an array of binary + /// structures, the nodes, which are a major part of the BSP tree. + /// + /// Every BSPNODE structure represents a node in the BSP tree and + /// every node equals more or less a division step of the BSP algorithm. + /// Therefore, each node has an index (iPlane) referring to a plane + /// in the plane lump which devides the node into its two child nodes. + /// The childnodes are also stored as indexes. Contrary to the plane + /// index, the node index for the child is signed. If the index is + /// larger than 0, the index indicates a child node. If it is equal + /// to or smaller than zero (no valid array index), the bitwise + /// inversed value of the index gives an index into the leaves lump. + /// Additionally two points (nMins, nMaxs) span the bounding box + /// (AABB, axis aligned bounding box) delimitting the space of the node. + /// Finally firstFace indexes into the face lump and spezifies the + /// first of nFaces surfaces contained in this node. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class VbspNode : BspNode + { + /// + /// If all leaves below this node are in the same area, then + /// this is the area index. If not, this is -1. + /// + public short Area; + + /// + /// Pad to 32 bytes length + /// + public short Padding; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspNodesLump.cs b/SabreTools.Serialization/Models/BSP/VbspNodesLump.cs new file mode 100644 index 00000000..61b399c4 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspNodesLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class VbspNodesLump : Lump + { + /// + /// Nodes + /// + public VbspNode[]? Nodes { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspTexinfo.cs b/SabreTools.Serialization/Models/BSP/VbspTexinfo.cs new file mode 100644 index 00000000..38fc87d2 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspTexinfo.cs @@ -0,0 +1,72 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The texinfo lump contains informations about how textures are + /// applied to surfaces. The lump itself is an array of binary data + /// structures. + /// + /// This struct is mainly responsible for the calculation of the texture + /// coordinates (vS, fSShift, vT, fTShift). This values determine the + /// position of the texture on the surface. The iMiptex integer refers + /// to the textures in the texture lump and would be the index in an + /// array of BSPMITEX structs. Finally, there are 4 Bytes used for flags. + /// Only one flag is used by the vanilla engine, being 0x1 for disabling + /// lightmaps and subdivision for the surface (used by sky and liquids). + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class VbspTexinfo + { + /// + /// Texture S-vector + /// + public Vector3D? TextureSVector; + + /// + /// Texture shift in the S direction + /// + public float TextureSShift; + + /// + /// Texture T-vector + /// + public Vector3D? TextureTVector; + + /// + /// Texture shift in the T direction + /// + public float TextureTShift; + + /// + /// Lightmap S-vector + /// + public Vector3D? LightmapSVector; + + /// + /// Lightmap shift in the S direction + /// + public float LightmapSShift; + + /// + /// Lightmap T-vector + /// + public Vector3D? LightmapTVector; + + /// + /// Lightmap shift in the T direction + /// + public float LightmapTShift; + + /// + /// Texture flags + /// + public TextureFlag Flags; + + /// + /// Pointer to texture name, size, etc. + /// + public int TexData; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VbspTexinfoLump.cs b/SabreTools.Serialization/Models/BSP/VbspTexinfoLump.cs new file mode 100644 index 00000000..833a1ce9 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VbspTexinfoLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class VbspTexinfoLump : Lump + { + /// + /// Texinfos + /// + public VbspTexinfo[]? Texinfos { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/Vector3D.cs b/SabreTools.Serialization/Models/BSP/Vector3D.cs new file mode 100644 index 00000000..2d4bb493 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/Vector3D.cs @@ -0,0 +1,17 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// There is a common struct used to represent a point in + /// 3-dimensional space which is used throughout the file + /// spec and the code of the hlbsp project. + /// + [StructLayout(LayoutKind.Sequential)] + public class Vector3D + { + public float X; + public float Y; + public float Z; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VerticesLump.cs b/SabreTools.Serialization/Models/BSP/VerticesLump.cs new file mode 100644 index 00000000..d7a6a620 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VerticesLump.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// This lump simply consists of all vertices of the BSP tree. + /// They are stored as a primitve array of triples of floats. + /// + /// + /// + public sealed class VerticesLump : Lump + { + /// + /// Vertices + /// + public Vector3D[]? Vertices { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/VisibilityLump.cs b/SabreTools.Serialization/Models/BSP/VisibilityLump.cs new file mode 100644 index 00000000..820e8021 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/VisibilityLump.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The VIS lump contains data, which is irrelevant to the actual + /// BSP tree, but offers a way to boost up the speed of the + /// renderer significantly. Especially complex maps profit from + /// the use if this data. This lump contains the so-called + /// Potentially Visible Sets (PVS) (also called VIS lists) in the + /// same amout of leaves of the tree, the user can enter (often + /// referred to as VisLeaves). The visiblilty lists are stored as + /// sequences of bitfields, which are run-length encoded. + /// + /// + /// + public sealed class VisibilityLump + { + public int NumClusters { get; set; } + + /// [numclusters][2] + public int[][]? ByteOffsets { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/WorldLight.cs b/SabreTools.Serialization/Models/BSP/WorldLight.cs new file mode 100644 index 00000000..14dadd18 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/WorldLight.cs @@ -0,0 +1,70 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.BSP +{ + /// + /// The worldlights lumps (Lump 15 for LDR and Lump 54 for HDR) + /// contain information on each static light entity in the world, + /// and are used to provide direct lighting for dynamically lit entities. + /// The data is generated by VRAD from the entity lump. VRAD uses + /// information from these lumps instead of referring to light + /// entities from Entity lump. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class WorldLight + { + public Vector3D? Origin; + + public Vector3D? Intensity; + + /// + /// For surfaces and spotlights + /// + public Vector3D? Normal; + + public int Cluster; + + public EmitType EmitType; + + public int Style; + + /// + /// Start of penumbra for emit_spotlight + /// + public float StopDot; + + /// + /// End of penumbra for emit_spotlight + /// + public float StopDot2; + + public float Exponent; + + /// + /// Cutoff distance + /// + public float Radius; + + // falloff for emit_spotlight + emit_point: + // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2) + + public float ConstantAttn; + + public float LinearAttn; + + public float QuadraticAttn; + + /// + /// Uses a combination of the DWL_FLAGS_ defines. + /// + public int Flags; + + public int Texinfo; + + /// + /// Entity that this light it relative to + /// + public int Owner; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BSP/WorldLightsLump.cs b/SabreTools.Serialization/Models/BSP/WorldLightsLump.cs new file mode 100644 index 00000000..ca472fb1 --- /dev/null +++ b/SabreTools.Serialization/Models/BSP/WorldLightsLump.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.BSP +{ + /// + public sealed class WorldLightsLump : Lump + { + /// + /// WorldLights + /// + public WorldLight[]? WorldLights { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/BZip2/Archive.cs b/SabreTools.Serialization/Models/BZip2/Archive.cs new file mode 100644 index 00000000..d16cfe86 --- /dev/null +++ b/SabreTools.Serialization/Models/BZip2/Archive.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.BZip2 +{ + /// + /// This is a placeholder model for future work + /// + public class Archive + { + + } +} diff --git a/SabreTools.Serialization/Models/BZip2/Constants.cs b/SabreTools.Serialization/Models/BZip2/Constants.cs new file mode 100644 index 00000000..f6601ca4 --- /dev/null +++ b/SabreTools.Serialization/Models/BZip2/Constants.cs @@ -0,0 +1,9 @@ +namespace SabreTools.Serialization.Models.BZip2 +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x42, 0x52, 0x68]; + + public const string SignatureString = "BRh"; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/BlockEntry.cs b/SabreTools.Serialization/Models/GCF/BlockEntry.cs new file mode 100644 index 00000000..4f52f388 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/BlockEntry.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BlockEntry + { + /// + /// Flags for the block entry. 0x200F0000 == Not used. + /// + public uint EntryFlags; + + /// + /// The offset for the data contained in this block entry in the file. + /// + public uint FileDataOffset; + + /// + /// The length of the data in this block entry. + /// + public uint FileDataSize; + + /// + /// The offset to the first data block of this block entry's data. + /// + public uint FirstDataBlockIndex; + + /// + /// The next block entry in the series. (N/A if == BlockCount.) + /// + public uint NextBlockEntryIndex; + + /// + /// The previous block entry in the series. (N/A if == BlockCount.) + /// + public uint PreviousBlockEntryIndex; + + /// + /// The offset of the block entry in the directory. + /// + public uint DirectoryIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/BlockEntryHeader.cs b/SabreTools.Serialization/Models/GCF/BlockEntryHeader.cs new file mode 100644 index 00000000..9bd3a7b2 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/BlockEntryHeader.cs @@ -0,0 +1,49 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BlockEntryHeader + { + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// Number of data blocks that point to data. + /// + public uint BlocksUsed; + + /// + /// Reserved + /// + public uint Dummy0; + + /// + /// Reserved + /// + public uint Dummy1; + + /// + /// Reserved + /// + public uint Dummy2; + + /// + /// Reserved + /// + public uint Dummy3; + + /// + /// Reserved + /// + public uint Dummy4; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/BlockEntryMap.cs b/SabreTools.Serialization/Models/GCF/BlockEntryMap.cs new file mode 100644 index 00000000..79a8d31d --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/BlockEntryMap.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + /// Part of version 5 but not version 6. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BlockEntryMap + { + /// + /// The previous block entry. (N/A if == BlockCount.) + /// + public uint PreviousBlockEntryIndex; + + /// + /// The next block entry. (N/A if == BlockCount.) + /// + public uint NextBlockEntryIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/BlockEntryMapHeader.cs b/SabreTools.Serialization/Models/GCF/BlockEntryMapHeader.cs new file mode 100644 index 00000000..82ce3fef --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/BlockEntryMapHeader.cs @@ -0,0 +1,37 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + /// Part of version 5 but not version 6. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BlockEntryMapHeader + { + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// Index of the first block entry. + /// + public uint FirstBlockEntryIndex; + + /// + /// Index of the last block entry. + /// + public uint LastBlockEntryIndex; + + /// + /// Reserved + /// + public uint Dummy0; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/ChecksumEntry.cs b/SabreTools.Serialization/Models/GCF/ChecksumEntry.cs new file mode 100644 index 00000000..ea8473a3 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/ChecksumEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumEntry + { + /// + /// Checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/ChecksumHeader.cs b/SabreTools.Serialization/Models/GCF/ChecksumHeader.cs new file mode 100644 index 00000000..78e6204c --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/ChecksumHeader.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumHeader + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Size of LPGCFCHECKSUMHEADER & LPGCFCHECKSUMMAPHEADER & in bytes. + /// + public uint ChecksumSize; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/ChecksumMapEntry.cs b/SabreTools.Serialization/Models/GCF/ChecksumMapEntry.cs new file mode 100644 index 00000000..4eb08b93 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/ChecksumMapEntry.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumMapEntry + { + /// + /// Number of checksums. + /// + public uint ChecksumCount; + + /// + /// Index of first checksum. + /// + public uint FirstChecksumIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/ChecksumMapHeader.cs b/SabreTools.Serialization/Models/GCF/ChecksumMapHeader.cs new file mode 100644 index 00000000..9bb2f514 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/ChecksumMapHeader.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumMapHeader + { + /// + /// Always 0x14893721 + /// + public uint Dummy0; + + /// + /// Always 0x00000001 + /// + public uint Dummy1; + + /// + /// Number of items. + /// + public uint ItemCount; + + /// + /// Number of checksums. + /// + public uint ChecksumCount; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/Constants.cs b/SabreTools.Serialization/Models/GCF/Constants.cs new file mode 100644 index 00000000..6bc131a6 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/Constants.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.GCF +{ + public static class Constants + { + /// + /// The maximum data allowed in a 32 bit checksum. + /// + public const int HL_GCF_CHECKSUM_LENGTH = 0x00008000; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DataBlockHeader.cs b/SabreTools.Serialization/Models/GCF/DataBlockHeader.cs new file mode 100644 index 00000000..0dcc114b --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DataBlockHeader.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DataBlockHeader + { + /// + /// GCF file version. This field is not part of all file versions. + /// + public uint LastVersionPlayed; + + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// Size of each data block in bytes. + /// + public uint BlockSize; + + /// + /// Offset to first data block. + /// + public uint FirstBlockOffset; + + /// + /// Number of data blocks that contain data. + /// + public uint BlocksUsed; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryCopyEntry.cs b/SabreTools.Serialization/Models/GCF/DirectoryCopyEntry.cs new file mode 100644 index 00000000..ce219a6e --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryCopyEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryCopyEntry + { + /// + /// Index of the directory item. + /// + public uint DirectoryIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryEntry.cs b/SabreTools.Serialization/Models/GCF/DirectoryEntry.cs new file mode 100644 index 00000000..23a9ffad --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryEntry.cs @@ -0,0 +1,45 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryEntry + { + /// + /// Offset to the directory item name from the end of the directory items. + /// + public uint NameOffset; + + /// + /// Size of the item. (If file, file size. If folder, num items.) + /// + public uint ItemSize; + + /// + /// Checksome index. (0xFFFFFFFF == None). + /// + public uint ChecksumIndex; + + /// + /// Flags for the directory item. (0x00000000 == Folder). + /// + [MarshalAs(UnmanagedType.U4)] + public HL_GCF_FLAG DirectoryFlags; + + /// + /// Index of the parent directory item. (0xFFFFFFFF == None). + /// + public uint ParentIndex; + + /// + /// Index of the next directory item. (0x00000000 == None). + /// + public uint NextIndex; + + /// + /// Index of the first directory item. (0x00000000 == None). + /// + public uint FirstIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryHeader.cs b/SabreTools.Serialization/Models/GCF/DirectoryHeader.cs new file mode 100644 index 00000000..3a83a22f --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryHeader.cs @@ -0,0 +1,79 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryHeader + { + /// + /// Always 0x00000004 + /// + public uint Dummy0; + + /// + /// Cache ID. + /// + public uint CacheID; + + /// + /// GCF file version. + /// + public uint LastVersionPlayed; + + /// + /// Number of items in the directory. + /// + public uint ItemCount; + + /// + /// Number of files in the directory. + /// + public uint FileCount; + + /// + /// Always 0x00008000. Data per checksum? + /// + public uint Dummy1; + + /// + /// Size of lpGCFDirectoryEntries & lpGCFDirectoryNames & lpGCFDirectoryInfo1Entries & lpGCFDirectoryInfo2Entries & lpGCFDirectoryCopyEntries & lpGCFDirectoryLocalEntries in bytes. + /// + public uint DirectorySize; + + /// + /// Size of the directory names in bytes. + /// + public uint NameSize; + + /// + /// Number of Info1 entires. + /// + public uint Info1Count; + + /// + /// Number of files to copy. + /// + public uint CopyCount; + + /// + /// Number of files to keep local. + /// + public uint LocalCount; + + /// + /// Reserved + /// + public uint Dummy2; + + /// + /// Reserved + /// + public uint Dummy3; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryInfo1Entry.cs b/SabreTools.Serialization/Models/GCF/DirectoryInfo1Entry.cs new file mode 100644 index 00000000..f0e1b114 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryInfo1Entry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryInfo1Entry + { + /// + /// Reserved + /// + public uint Dummy0; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryInfo2Entry.cs b/SabreTools.Serialization/Models/GCF/DirectoryInfo2Entry.cs new file mode 100644 index 00000000..67b98f96 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryInfo2Entry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryInfo2Entry + { + /// + /// Reserved + /// + public uint Dummy0; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryLocalEntry.cs b/SabreTools.Serialization/Models/GCF/DirectoryLocalEntry.cs new file mode 100644 index 00000000..79b94f4f --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryLocalEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryLocalEntry + { + /// + /// Index of the directory item. + /// + public uint DirectoryIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryMapEntry.cs b/SabreTools.Serialization/Models/GCF/DirectoryMapEntry.cs new file mode 100644 index 00000000..dc9b84ca --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryMapEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryMapEntry + { + /// + /// Index of the first data block. (N/A if == BlockCount.) + /// + public uint FirstBlockIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/DirectoryMapHeader.cs b/SabreTools.Serialization/Models/GCF/DirectoryMapHeader.cs new file mode 100644 index 00000000..5f08fcfc --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/DirectoryMapHeader.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + /// Added in version 4 or version 5. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryMapHeader + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Always 0x00000000 + /// + public uint Dummy1; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/Enums.cs b/SabreTools.Serialization/Models/GCF/Enums.cs new file mode 100644 index 00000000..71d0efa2 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/Enums.cs @@ -0,0 +1,38 @@ +using System; + +namespace SabreTools.Serialization.Models.GCF +{ + [Flags] + public enum HL_GCF_FLAG : uint + { + /// + /// Folder + /// + HL_GCF_FLAG_FOLDER = 0x00000000, + + /// + /// Don't overwrite the item if copying it to the disk and the item already exists. + /// + HL_GCF_FLAG_COPY_LOCAL_NO_OVERWRITE = 0x00000001, + + /// + /// The item is to be copied to the disk. + /// + HL_GCF_FLAG_COPY_LOCAL = 0x0000000A, + + /// + /// Backup the item before overwriting it. + /// + HL_GCF_FLAG_BACKUP_LOCAL = 0x00000040, + + /// + /// The item is encrypted. + /// + HL_GCF_FLAG_ENCRYPTED = 0x00000100, + + /// + /// The item is a file. + /// + HL_GCF_FLAG_FILE = 0x00004000, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/File.cs b/SabreTools.Serialization/Models/GCF/File.cs new file mode 100644 index 00000000..fdb259f7 --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/File.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + /// Half-Life Game Cache File + /// + /// + public sealed class File + { + /// + /// Header data + /// + public Header? Header { get; set; } + + /// + /// Block entry header data + /// + public BlockEntryHeader? BlockEntryHeader { get; set; } + + /// + /// Block entries data + /// + public BlockEntry[]? BlockEntries { get; set; } + + /// + /// Fragmentation map header data + /// + public FragmentationMapHeader? FragmentationMapHeader { get; set; } + + /// + /// Fragmentation map data + /// + public FragmentationMap[]? FragmentationMaps { get; set; } + + /// + /// Block entry map header data + /// + /// Part of version 5 but not version 6. + public BlockEntryMapHeader? BlockEntryMapHeader { get; set; } + + /// + /// Block entry map data + /// + /// Part of version 5 but not version 6. + public BlockEntryMap[]? BlockEntryMaps { get; set; } + + /// + /// Directory header data + /// + public DirectoryHeader? DirectoryHeader { get; set; } + + /// + /// Directory entries data + /// + public DirectoryEntry[]? DirectoryEntries { get; set; } + + /// + /// Directory names data + /// + public Dictionary? DirectoryNames { get; set; } + + /// + /// Directory info 1 entries data + /// + public DirectoryInfo1Entry[]? DirectoryInfo1Entries { get; set; } + + /// + /// Directory info 2 entries data + /// + public DirectoryInfo2Entry[]? DirectoryInfo2Entries { get; set; } + + /// + /// Directory copy entries data + /// + public DirectoryCopyEntry[]? DirectoryCopyEntries { get; set; } + + /// + /// Directory local entries data + /// + public DirectoryLocalEntry[]? DirectoryLocalEntries { get; set; } + + /// + /// Directory map header data + /// + public DirectoryMapHeader? DirectoryMapHeader { get; set; } + + /// + /// Directory map entries data + /// + public DirectoryMapEntry[]? DirectoryMapEntries { get; set; } + + /// + /// Checksum header data + /// + public ChecksumHeader? ChecksumHeader { get; set; } + + /// + /// Checksum map header data + /// + public ChecksumMapHeader? ChecksumMapHeader { get; set; } + + /// + /// Checksum map entries data + /// + public ChecksumMapEntry[]? ChecksumMapEntries { get; set; } + + /// + /// Checksum entries data + /// + public ChecksumEntry[]? ChecksumEntries { get; set; } + + /// + /// Data block header data + /// + public DataBlockHeader? DataBlockHeader { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/FragmentationMap.cs b/SabreTools.Serialization/Models/GCF/FragmentationMap.cs new file mode 100644 index 00000000..af07e43c --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/FragmentationMap.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class FragmentationMap + { + /// + /// The index of the next data block. + /// + public uint NextDataBlockIndex; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/FragmentationMapHeader.cs b/SabreTools.Serialization/Models/GCF/FragmentationMapHeader.cs new file mode 100644 index 00000000..c1a250ed --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/FragmentationMapHeader.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class FragmentationMapHeader + { + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// The index of the first unused fragmentation map entry. + /// + public uint FirstUnusedEntry; + + /// + /// The block entry terminator; 0 = 0x0000ffff or 1 = 0xffffffff. + /// + public uint Terminator; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GCF/Header.cs b/SabreTools.Serialization/Models/GCF/Header.cs new file mode 100644 index 00000000..cbd5516c --- /dev/null +++ b/SabreTools.Serialization/Models/GCF/Header.cs @@ -0,0 +1,64 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.GCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Header + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Always 0x00000001 + /// + public uint MajorVersion; + + /// + /// GCF version number. + /// + public uint MinorVersion; + + /// + /// Cache ID + /// + public uint CacheID; + + /// + /// Last version played + /// + public uint LastVersionPlayed; + + /// + /// Reserved + /// + public uint Dummy1; + + /// + /// Reserved + /// + public uint Dummy2; + + /// + /// Total size of GCF file in bytes. + /// + public uint FileSize; + + /// + /// Size of each data block in bytes. + /// + public uint BlockSize; + + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// Reserved + /// + public uint Dummy3; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/Archive.cs b/SabreTools.Serialization/Models/GZIP/Archive.cs new file mode 100644 index 00000000..567a3e8c --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/Archive.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public sealed class Archive + { + /// + /// Header including optional fields + /// + public Header? Header { get; set; } + + // Compressed blocks live here + + /// + /// Trailer + /// + public Trailer? Trailer { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/Constants.cs b/SabreTools.Serialization/Models/GZIP/Constants.cs new file mode 100644 index 00000000..b6c844f7 --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/Constants.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public static class Constants + { + public const byte ID1 = 0x1F; + + public const byte ID2 = 0x8B; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/Enums.cs b/SabreTools.Serialization/Models/GZIP/Enums.cs new file mode 100644 index 00000000..1d8be63d --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/Enums.cs @@ -0,0 +1,147 @@ +using System; + +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public enum CompressionMethod : byte + { + RESERVED0 = 0, + RESERVED1 = 1, + RESERVED2 = 2, + RESERVED3 = 3, + RESERVED4 = 4, + RESERVED5 = 5, + RESERVED6 = 6, + RESERVED7 = 7, + + Deflate = 8, + } + + /// + [Flags] + public enum ExtraFlags : byte + { + /// + /// Compressor used maximum compression, slowest algorithm + /// + MaximumCompression = 0x02, + + /// + /// Compressor used fastest algorithm + /// + FastestAlgorithm = 0x04, + } + + /// + [Flags] + public enum Flags : byte + { + /// + /// The file is probably ASCII text + /// + FTEXT = 0x01, + + /// + /// CRC-16 for the gzip header is present + /// + FHCRC = 0x02, + + /// + /// Optional extra fields are present + /// + FEXTRA = 0x04, + + /// + /// Original filename is present + /// + FNAME = 0x08, + + /// + /// Zero-terminated file comment is present + /// + FCOMMENT = 0x10, + + RESERVED5 = 0x20, + RESERVED6 = 0x40, + RESERVED7 = 0x80, + } + + /// + public enum OperatingSystem : byte + { + /// + /// FAT filesystem (MS-DOS, OS/2, NT/Win32) + /// + FAT = 0, + + /// + /// Amiga + /// + Amiga = 1, + + /// + /// VMS (or OpenVMS) + /// + VMS = 2, + + /// + /// Unix + /// + Unix = 3, + + /// + /// VM/CMS + /// + VMCMS = 4, + + /// + /// Atari TOS + /// + AtariTOS = 5, + + /// + /// HPFS filesystem (OS/2, NT) + /// + HPFS = 6, + + /// + /// Macintosh + /// + Macintosh = 7, + + /// + /// Z-System + /// + ZSystem = 8, + + /// + /// CP/M + /// + CPM = 9, + + /// + /// TOPS-20 + /// + TOPS20 = 10, + + /// + /// NTFS filesystem (NT) + /// + NTFS = 11, + + /// + /// QDOS + /// + QDOS = 12, + + /// + /// Acorn RISCOS + /// + AcornRISCOS = 13, + + /// + /// unknown + /// + Unknown = 255, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/ExtraFieldData.cs b/SabreTools.Serialization/Models/GZIP/ExtraFieldData.cs new file mode 100644 index 00000000..22f7fe7c --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/ExtraFieldData.cs @@ -0,0 +1,26 @@ +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public sealed class ExtraFieldData + { + /// + /// SI1 and SI2 provide a subfield ID, typically two ASCII letters + /// with some mnemonic value. + /// + public byte SubfieldID1 { get; set; } + + /// + /// SI1 and SI2 provide a subfield ID, typically two ASCII letters + /// with some mnemonic value. + /// + public byte SubfieldID2 { get; set; } + + /// + /// LEN gives the length of the subfield data, excluding the 4 + /// initial bytes. + /// + public ushort Length { get; set; } + + public byte[]? Data { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/Header.cs b/SabreTools.Serialization/Models/GZIP/Header.cs new file mode 100644 index 00000000..48a6cef7 --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/Header.cs @@ -0,0 +1,88 @@ +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public sealed class Header + { + /// + /// IDentification 1 (0x1F) + /// + public byte ID1 { get; set; } + + /// + /// IDentification 2 (0x8B) + /// + public byte ID2 { get; set; } + + /// + /// Compression Method + /// + public CompressionMethod CompressionMethod { get; set; } + + /// + /// FLaGs + /// + public Flags Flags { get; set; } + + /// + /// Modification TIME + /// + /// This gives the most recent modification time of the original + /// file being compressed. The time is in Unix format, i.e., + /// seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this + /// may cause problems for MS-DOS and other systems that use + /// local rather than Universal time.) If the compressed data + /// did not come from a file, MTIME is set to the time at which + /// compression started. MTIME = 0 means no time stamp is + /// available. + /// + public uint LastModifiedTime { get; set; } + + /// + /// eXtra FLags + /// + public ExtraFlags ExtraFlags { get; set; } + + /// + /// Operating System + /// + /// This identifies the type of file system on which compression + /// took place. This may be useful in determining end-of-line + /// convention for text files. + /// + public OperatingSystem OperatingSystem { get; set; } + + /// + /// eXtra LENgth + /// + /// If FLG.FEXTRA is set, this gives the length of the optional + /// extra field. + /// + public ushort ExtraLength { get; set; } + + /// + /// Extra field + /// + /// If the FLG.FEXTRA bit is set, an "extra field" is present in + /// the header, with total length XLEN bytes. It consists of a + /// series of subfields, each of the form . + /// + public ExtraFieldData[]? ExtraField { get; set; } + + /// + /// Original filename before compression, null-terminated + /// + public string? OriginalFileName { get; set; } + + /// + /// File comment, null terminated + /// + public string? FileComment { get; set; } + + /// + /// The CRC16 consists of the two least significant bytes of the + /// CRC32 for all bytes of the gzip header up to and not including + /// the CRC16. + /// + public ushort? CRC16 { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/GZIP/Trailer.cs b/SabreTools.Serialization/Models/GZIP/Trailer.cs new file mode 100644 index 00000000..7f8e1699 --- /dev/null +++ b/SabreTools.Serialization/Models/GZIP/Trailer.cs @@ -0,0 +1,26 @@ +namespace SabreTools.Serialization.Models.GZIP +{ + /// + public sealed class Trailer + { + /// + /// CRC-32 + /// + /// This contains a Cyclic Redundancy Check value of the + /// uncompressed data computed according to CRC-32 algorithm + /// used in the ISO 3309 standard and in section 8.1.1.6.2 of + /// ITU-T recommendation V.42. (See http://www.iso.ch for + /// ordering ISO documents. See gopher://info.itu.ch for an + /// online version of ITU-T V.42.) + /// + public uint CRC32 { get; set; } + + /// + /// Input SIZE + /// + /// This contains the size of the original (uncompressed) input + /// data modulo 2^32. + /// + public uint InputSize { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/Archive.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Archive.cs new file mode 100644 index 00000000..b9035784 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Archive.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + /// + public class Archive + { + /// + /// Archive header information + /// + public Header? Header { get; set; } + + /// + /// Directories found in the archive + /// + public Directory[]? Directories { get; set; } + + /// + /// Files found in the archive + /// + public File[]? Files { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/Constants.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Constants.cs new file mode 100644 index 00000000..44352f1f --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Constants.cs @@ -0,0 +1,9 @@ +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + public static class Constants + { + public const uint HeaderSignature = 0x8C655D13; + + public static readonly byte[] HeaderSignatureBytes = [0x13, 0x5D, 0x65, 0x8C]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/Directory.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Directory.cs new file mode 100644 index 00000000..96b2c6c3 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Directory.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + /// + [StructLayout(LayoutKind.Sequential)] + public class Directory + { + /// + /// Number of files in the directory + /// + public ushort FileCount; + + /// + /// Size of the chunk + /// + public ushort ChunkSize; + + /// + /// Length of the following ASCII string + /// + public ushort NameLength; + + /// + /// Name as an ASCII string + /// + public string? Name; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/Enums.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Enums.cs new file mode 100644 index 00000000..fe847739 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Enums.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + public enum Attributes : byte + { + READONLY = 0x01, + HIDDEN = 0x02, + SYSTEM = 0x04, + UNCOMPRESSED = 0x10, + ARCHIVE = 0x20, + } +} diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/File.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/File.cs new file mode 100644 index 00000000..58c248ba --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/File.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; + +#pragma warning disable CS0618 // 'UnmanagedType.AnsiBStr' is obsolete +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + /// + [StructLayout(LayoutKind.Sequential)] + public class File + { + public byte VolumeEnd; + + public ushort Index; + + public uint UncompressedSize; + + public uint CompressedSize; + + public uint Offset; + + public uint DateTime; + + public uint Reserved0; + + public ushort ChunkSize; + + [MarshalAs(UnmanagedType.U1)] + public Attributes Attrib; + + public byte IsSplit; + + public byte Reserved1; + + public byte VolumeStart; + + [MarshalAs(UnmanagedType.AnsiBStr)] + public string? Name; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldArchiveV3/Header.cs b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Header.cs new file mode 100644 index 00000000..d7da26cd --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldArchiveV3/Header.cs @@ -0,0 +1,53 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.InstallShieldArchiveV3 +{ + /// + [StructLayout(LayoutKind.Sequential)] + public class Header + { + public uint Signature1; + + public uint Signature2; + + public ushort Reserved0; + + public ushort IsMultivolume; + + public ushort FileCount; + + public uint DateTime; + + public uint CompressedSize; + + public uint UncompressedSize; + + public uint Reserved1; + + /// + /// Set in first vol only, zero in subsequent vols + /// + public byte VolumeTotal; + + /// + /// [1...n] + /// + public byte VolumeNumber; + + public byte Reserved2; + + public uint SplitBeginAddress; + + public uint SplitEndAddress; + + public uint TocAddress; + + public uint Reserved3; + + public ushort DirCount; + + public uint Reserved4; + + public uint Reserved5; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/Cabinet.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/Cabinet.cs new file mode 100644 index 00000000..f38c3e5a --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/Cabinet.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + /// + public sealed class Cabinet + { + #region Headers + + /// + /// Common header + /// + public CommonHeader? CommonHeader { get; set; } + + /// + /// Volume header + /// + public VolumeHeader? VolumeHeader { get; set; } + + /// + /// Descriptor + /// + public Descriptor? Descriptor { get; set; } + + #endregion + + #region File Descriptors + + /// + /// Offsets to all file descriptors + /// + public uint[]? FileDescriptorOffsets { get; set; } + + /// + /// Directory names + /// + public string[]? DirectoryNames { get; set; } + + /// + /// Standard file descriptors + /// + public FileDescriptor[]? FileDescriptors { get; set; } + + #endregion + + #region File Groups + + /// + /// File group offset to offset list mapping + /// + public Dictionary? FileGroupOffsets { get; set; } + + /// + /// File groups + /// + public FileGroup[]? FileGroups { get; set; } + + #endregion + + #region Components + + /// + /// Component offset to offset list mapping + /// + public Dictionary? ComponentOffsets { get; set; } + + /// + /// Components + /// + public Component[]? Components { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/CommonHeader.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/CommonHeader.cs new file mode 100644 index 00000000..a67fcbe7 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/CommonHeader.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class CommonHeader + { + /// + /// "ISc(" + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Encoded version + /// + public uint Version; + + /// + /// Volume information + /// + public uint VolumeInfo; + + /// + /// Offset to cabinet descriptor + /// + public uint DescriptorOffset; + + /// + /// Cabinet descriptor size + /// + public uint DescriptorSize; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/Component.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/Component.cs new file mode 100644 index 00000000..4bfe4916 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/Component.cs @@ -0,0 +1,175 @@ +using System; + +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + public sealed class Component + { + /// + /// Offset to the component identifier + /// + public uint IdentifierOffset { get; set; } + + /// + /// Component identifier + /// + public string? Identifier { get; set; } + + /// + /// Offset to the component descriptor + /// + public uint DescriptorOffset { get; set; } + + /// + /// Offset to the display name + /// + public uint DisplayNameOffset { get; set; } + + /// + /// Display name + /// + public string? DisplayName { get; set; } + + /// + /// Component status + /// + public ComponentStatus Status { get; set; } + + /// + /// Offset to the password + /// + public uint PasswordOffset { get; set; } + + /// + /// Misc offset + /// + public uint MiscOffset { get; set; } + + /// + /// Component index + /// + public ushort ComponentIndex { get; set; } + + /// + /// Offset to the component name + /// + public uint NameOffset { get; set; } + + /// + /// Component name + /// + public string? Name { get; set; } + + /// + /// Offset to the CD-ROM folder + /// + public uint CDRomFolderOffset { get; set; } + + /// + /// Offset to the HTTP location + /// + public uint HTTPLocationOffset { get; set; } + + /// + /// Offset to the FTP location + /// + public uint FTPLocationOffset { get; set; } + + /// + /// Unknown GUIDs + /// + public Guid[]? Guid { get; set; } = new Guid[2]; + + /// + /// Offset to the component CLSID + /// + public uint CLSIDOffset { get; set; } + + /// + /// Component CLSID + /// + public Guid CLSID { get; set; } + + /// + /// Reserved + /// + /// 28 bytes, see CompAttrs + public byte[]? Reserved2 { get; set; } + + /// + /// Reserved + /// + /// 2 bytes (<= v5), 1 byte (> v5) + public byte[]? Reserved3 { get; set; } + + /// + /// Number of depends(?) + /// + public ushort DependsCount { get; set; } + + /// + /// Offset to depends(?) + /// + public uint DependsOffset { get; set; } + + /// + /// Number of file groups + /// + public uint FileGroupCount { get; set; } + + /// + /// Offset to the file group names + /// + public uint FileGroupNamesOffset { get; set; } + + /// + /// File group names + /// + public string[]? FileGroupNames { get; set; } + + /// + /// Number of X3(?) + /// + public ushort X3Count { get; set; } + + /// + /// Offset to X3(?) + /// + public uint X3Offset { get; set; } + + /// + /// Number of sub-components + /// + public ushort SubComponentsCount { get; set; } + + /// + /// Offset to the sub-components + /// + public uint SubComponentsOffset { get; set; } + + /// + /// Offset to the next component + /// + public uint NextComponentOffset { get; set; } + + /// + /// Offset to on installing text + /// + public uint OnInstallingOffset { get; set; } + + /// + /// Offset to on installed text + /// + public uint OnInstalledOffset { get; set; } + + /// + /// Offset to on uninstalling text + /// + public uint OnUninstallingOffset { get; set; } + + /// + /// Offset to on uninstalled text + /// + public uint OnUninstalledOffset { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/Constants.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/Constants.cs new file mode 100644 index 00000000..a56dfb02 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/Constants.cs @@ -0,0 +1,27 @@ +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x49, 0x53, 0x63, 0x28]; + + public const string SignatureString = "ISc("; + + public const uint SignatureUInt32 = 0x28635349; + + public const string HEADER_SUFFIX = "hdr"; + + public const string CABINET_SUFFIX = "cab"; + + public const int COMMON_HEADER_SIZE = 20; + + public const int VOLUME_HEADER_SIZE_V5 = 40; + + public const int VOLUME_HEADER_SIZE_V6 = 64; + + // TODO: Determine how the value "71" was chosen here + public const int MAX_FILE_GROUP_COUNT = 71; + + // TODO: Determine how the value "71" was chosen here + public const int MAX_COMPONENT_COUNT = 71; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/Descriptor.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/Descriptor.cs new file mode 100644 index 00000000..d318fa58 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/Descriptor.cs @@ -0,0 +1,126 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Descriptor + { + /// + /// Offset to the descriptor strings + /// + public uint StringsOffset; + + /// + /// Reserved + /// + public uint Reserved0; + + /// + /// Offset to the component list + /// + public uint ComponentListOffset; + + /// + /// Offset to the file table + /// + public uint FileTableOffset; + + /// + /// Reserved + /// + public uint Reserved1; + + /// + /// Size of the file table + /// + public uint FileTableSize; + + /// + /// Redundant size of the file table + /// + public uint FileTableSize2; + + /// + /// Number of directories + /// + public ushort DirectoryCount; + + /// + /// Reserved + /// + public uint Reserved2; + + /// + /// Reserved + /// + public ushort Reserved3; + + /// + /// Reserved + /// + public uint Reserved4; + + /// + /// Number of files + /// + public uint FileCount; + + /// + /// Redundant offset to the file table + /// + public uint FileTableOffset2; + + /// + /// Number of component table infos + /// + public ushort ComponentTableInfoCount; + + /// + /// Offset to the component table + /// + public uint ComponentTableOffset; + + /// + /// Reserved + /// + public uint Reserved5; + + /// + /// Reserved + /// + public uint Reserved6; + + /// + /// Offsets to the file groups + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 71)] + public uint[]? FileGroupOffsets; + + /// + /// Offsets to the components + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 71)] + public uint[]? ComponentOffsets; + + /// + /// Offset to the setup types + /// + public uint SetupTypesOffset; + + /// + /// Offset to the setup table + /// + public uint SetupTableOffset; + + /// + /// Reserved + /// + public uint Reserved7; + + /// + /// Reserved + /// + public uint Reserved8; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/Enums.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/Enums.cs new file mode 100644 index 00000000..a24214bd --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/Enums.cs @@ -0,0 +1,103 @@ +using System; + +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// i6comp02 + [Flags] + public enum ComponentStatus : ushort + { + /// + /// Critical + /// + COMP_STAT_CRITICAL = 0x01, + + /// + /// Recommended + /// + COMP_STAT_RECOMMEND = 0x02, + + /// + /// Standard + /// + COMP_STAT_STANDARD = 0x04, + } + + /// + [Flags] + public enum FileFlags : ushort + { + FILE_SPLIT = 1, + FILE_OBFUSCATED = 2, + FILE_COMPRESSED = 4, + FILE_INVALID = 8, + } + + /// i6comp02 + [Flags] + public enum FileGroupAttributes : ushort + { + /// + /// Shared + /// + FGATTR_SHARED = 0x01, + + /// + /// Encrypted + /// + FGATTR_ENCRYPTED = 0x02, + + /// + /// Compressed + /// + FGATTR_COMPRESSED = 0x04, + + /// + /// Self-Registering + /// + FGATTR_SELFREGISTER = 0x10, + + /// + /// Potentially locked + /// + FGATTR_LOCKED = 0x20, + + /// + /// Uninstall + /// + FGATTR_UNINSTALL = 0x40, + } + + /// i6comp02 + [Flags] + public enum FileGroupFlags : uint + { + /// + /// Always overwrite + /// + FGDESC_ALWAYS_OVERWRITE = 0x001, + + /// + /// Never overwrite + /// + FGDESC_NEVER_OVERWRITE = 0x002, + + /// + /// Overwrite if newer date + /// + FGDESC_NEWER_DATE = 0x020, + + /// + /// Overwrite if newer version + /// + FGDESC_NEWER_VERSION = 0x200, + } + + /// + public enum LinkFlags : byte + { + LINK_NONE = 0, + LINK_PREV = 1, + LINK_NEXT = 2, + LINK_BOTH = 3, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/FileDescriptor.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/FileDescriptor.cs new file mode 100644 index 00000000..b2fe71be --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/FileDescriptor.cs @@ -0,0 +1,66 @@ +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + public sealed class FileDescriptor + { + /// + /// Offset to the file descriptor name + /// + public uint NameOffset { get; set; } + + /// + /// File descriptor name + /// + public string? Name { get; set; } + + /// + /// Directory index + /// + public uint DirectoryIndex { get; set; } + + /// + /// File flags + /// + public FileFlags Flags { get; set; } + + /// + /// Size of the entry when expanded + /// + public ulong ExpandedSize { get; set; } + + /// + /// Size of the entry when compressed + /// + public ulong CompressedSize { get; set; } + + /// + /// Offset to the entry data + /// + public ulong DataOffset { get; set; } + + /// + /// MD5 of the entry data + /// + public byte[]? MD5 { get; set; } + + /// + /// Volume number + /// + public ushort Volume { get; set; } + + /// + /// Link previous + /// + public uint LinkPrevious { get; set; } + + /// + /// Link next + /// + public uint LinkNext { get; set; } + + /// + /// Link flags + /// + public LinkFlags LinkFlags { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/FileGroup.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/FileGroup.cs new file mode 100644 index 00000000..61a42030 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/FileGroup.cs @@ -0,0 +1,87 @@ +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + /// Additional info from i6comp02 + public sealed class FileGroup + { + /// + /// Offset to the file group name + /// + public uint NameOffset { get; set; } + + /// + /// File group name + /// + public string? Name { get; set; } + + /// + /// Size of the expanded data + /// + public uint ExpandedSize { get; set; } + + /// + /// Size of the compressed data + /// + public uint CompressedSize { get; set; } + + /// + /// Attributes (junk2) + /// + public FileGroupAttributes Attributes { get; set; } + + /// + /// Index of the first file + /// + public uint FirstFile { get; set; } + + /// + /// Index of the last file + /// + public uint LastFile { get; set; } + + /// + /// Unknown string offset + /// + public uint UnknownStringOffset { get; set; } + + /// + /// Offset to the operating system (Var4) + /// + public uint OperatingSystemOffset { get; set; } + + /// + /// Offset to the language (Var1) + /// + public uint LanguageOffset { get; set; } + + /// + /// Offset to the HTTP location + /// + public uint HTTPLocationOffset { get; set; } + + /// + /// Offset to the FTP location + /// + public uint FTPLocationOffset { get; set; } + + /// + /// Misc offset + /// + public uint MiscOffset { get; set; } + + /// + /// Offset to the target directory + /// + public uint TargetDirectoryOffset { get; set; } + + /// + /// Overwrite setting flags + /// + public FileGroupFlags OverwriteFlags { get; set; } + + /// + /// Reserved + /// + public uint[]? Reserved { get; set; } = new uint[4]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/OffsetList.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/OffsetList.cs new file mode 100644 index 00000000..7f038cb9 --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/OffsetList.cs @@ -0,0 +1,14 @@ +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + public sealed class OffsetList + { + public uint NameOffset { get; set; } + + public string? Name { get; set; } + + public uint DescriptorOffset { get; set; } + + public uint NextOffset { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/InstallShieldCabinet/VolumeHeader.cs b/SabreTools.Serialization/Models/InstallShieldCabinet/VolumeHeader.cs new file mode 100644 index 00000000..29fd7e0d --- /dev/null +++ b/SabreTools.Serialization/Models/InstallShieldCabinet/VolumeHeader.cs @@ -0,0 +1,39 @@ +namespace SabreTools.Serialization.Models.InstallShieldCabinet +{ + /// + /// TODO: Should standard and high values be combined? + public sealed class VolumeHeader + { + public uint DataOffset { get; set; } + + public uint DataOffsetHigh { get; set; } + + public uint FirstFileIndex { get; set; } + + public uint LastFileIndex { get; set; } + + public uint FirstFileOffset { get; set; } + + public uint FirstFileOffsetHigh { get; set; } + + public uint FirstFileSizeExpanded { get; set; } + + public uint FirstFileSizeExpandedHigh { get; set; } + + public uint FirstFileSizeCompressed { get; set; } + + public uint FirstFileSizeCompressedHigh { get; set; } + + public uint LastFileOffset { get; set; } + + public uint LastFileOffsetHigh { get; set; } + + public uint LastFileSizeExpanded { get; set; } + + public uint LastFileSizeExpandedHigh { get; set; } + + public uint LastFileSizeCompressed { get; set; } + + public uint LastFileSizeCompressedHigh { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/Constants.cs b/SabreTools.Serialization/Models/LZ/Constants.cs new file mode 100644 index 00000000..907ec4b8 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/Constants.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.LZ +{ + public static class Constants + { + public const string KWAJPrefix = "KWAJ"; + + public static readonly byte[] KWAJSignatureBytes = [0x4B, 0x57, 0x41, 0x4A, 0x88, 0xF0, 0x27, 0xD1]; + + public const string QBasicPrefix = "SZ "; + + public static readonly byte[] QBasicSignatureBytes = [0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1]; + + public const string SZDDPrefix = "SZDD"; + + public static readonly byte[] SZDDSignatureBytes = [0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/Enums.cs b/SabreTools.Serialization/Models/LZ/Enums.cs new file mode 100644 index 00000000..60a3a5dd --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/Enums.cs @@ -0,0 +1,82 @@ +using System; + +namespace SabreTools.Serialization.Models.LZ +{ + /// + public enum KWAJCompressionType : ushort + { + /// + /// No compression + /// + NoCompression = 0, + + /// + /// No compression, data is XORed with byte 0xFF + /// + NoCompressionXor = 1, + + /// + /// The same compression method as the QBasic variant of SZDD + /// + QBasic = 2, + + /// + /// LZ + Huffman "Jeff Johnson" compression + /// + LZH = 3, + + /// + /// MS-ZIP + /// + MSZIP = 4, + } + + /// + [Flags] + public enum KWAJHeaderFlags : ushort + { + /// + /// Header extensions contains 4-byte decompressed length + /// + HasDecompressedLength = 0x0001, + + /// + /// Header extensions contains 2-byte unknown value + /// + HasUnknownFlag = 0x0002, + + /// + /// Header extensions contains 2-byte prefix followed by + /// that many bytes of (unknown purpose) data + /// + HasPrefixedData = 0x0004, + + /// + /// Header extensions contains null-terminated string of + /// max length 8 representing the file name + /// + HasFileName = 0x0008, + + /// + /// Header extensions contains null-terminated string of + /// max length 3 representing the file name + /// + HasFileExtension = 0x0010, + + /// + /// Header extensions contains 2-byte prefix followed by + /// that many bytes of (arbitrary text) data + /// + HasAdditionalText = 0x0020, + } + + /// + /// + public enum ExpandCompressionType : byte + { + /// + /// Only valid compression type: 'A' + /// + A = 0x41, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/KWAJFile.cs b/SabreTools.Serialization/Models/LZ/KWAJFile.cs new file mode 100644 index 00000000..176b2d7a --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/KWAJFile.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// LZ variant with variable compression + /// + /// + public sealed class KWAJFile + { + /// + /// Header + /// + public KWAJHeader? Header { get; set; } + + /// + /// Optional extensions defined by + /// + public KWAJHeaderExtensions? HeaderExtensions { get; set; } + + // Followed immediately by compressed data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/KWAJHeader.cs b/SabreTools.Serialization/Models/LZ/KWAJHeader.cs new file mode 100644 index 00000000..769fcf65 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/KWAJHeader.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// LZ variant with variable compression + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class KWAJHeader + { + /// + /// "KWAJ" signature + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public byte[]? Magic; + + /// + /// Compression method + /// + [MarshalAs(UnmanagedType.U2)] + public KWAJCompressionType CompressionType; + + /// + /// File offset of compressed data + /// + public ushort DataOffset; + + /// + /// Header flags to mark header extensions + /// + [MarshalAs(UnmanagedType.U2)] + public KWAJHeaderFlags HeaderFlags; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/KWAJHeaderExtensions.cs b/SabreTools.Serialization/Models/LZ/KWAJHeaderExtensions.cs new file mode 100644 index 00000000..f7ca8547 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/KWAJHeaderExtensions.cs @@ -0,0 +1,51 @@ +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// Additional information stored after the KWAJ header + /// + /// + public sealed class KWAJHeaderExtensions + { + /// + /// Decompressed length of file + /// + public uint? DecompressedLength { get; set; } + + /// + /// Unknown purpose + /// + public ushort? UnknownPurpose { get; set; } + + /// + /// Length of + /// + public ushort? UnknownDataLength { get; set; } + + /// + /// Unknown purpose data whose length is defined + /// by + /// + public byte[]? UnknownData { get; set; } + + /// + /// Null-terminated string with max length 8: file name + /// + public string? FileName { get; set; } + + /// + /// Null-terminated string with max length 3: file extension + /// + public string? FileExtension { get; set; } + + /// + /// Length of + /// + public ushort? ArbitraryTextLength { get; set; } + + /// + /// Arbitrary text data whose length is defined + /// by + /// + public byte[]? ArbitraryText { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/QBasicFile.cs b/SabreTools.Serialization/Models/LZ/QBasicFile.cs new file mode 100644 index 00000000..dcebf115 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/QBasicFile.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// LZ variant used in QBasic 4.5 installer + /// + /// + public sealed class QBasicFile + { + /// + /// Header + /// + public QBasicHeader? Header { get; set; } + + // Followed immediately by compressed data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/QBasicHeader.cs b/SabreTools.Serialization/Models/LZ/QBasicHeader.cs new file mode 100644 index 00000000..4216e7e9 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/QBasicHeader.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// LZ variant used in QBasic 4.5 installer + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class QBasicHeader + { + /// + /// "SZ" signature + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public byte[]? Magic; + + /// + /// The integer length of the file when unpacked + /// + public uint RealLength; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/SZDDFile.cs b/SabreTools.Serialization/Models/LZ/SZDDFile.cs new file mode 100644 index 00000000..5d6292a6 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/SZDDFile.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// Standard LZ variant + /// + /// + /// + public sealed class SZDDFile + { + /// + /// Header + /// + public SZDDHeader? Header { get; set; } + + // Followed immediately by compressed data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LZ/SZDDHeader.cs b/SabreTools.Serialization/Models/LZ/SZDDHeader.cs new file mode 100644 index 00000000..f360c196 --- /dev/null +++ b/SabreTools.Serialization/Models/LZ/SZDDHeader.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LZ +{ + /// + /// Standard LZ variant + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class SZDDHeader + { + /// + /// "SZDD" signature + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public byte[]? Magic; + + /// + /// Compression mode + /// + /// Only is supported + [MarshalAs(UnmanagedType.U1)] + public ExpandCompressionType CompressionType; + + /// + /// The character missing from the end of the filename + /// + /// 0 means unknown + [MarshalAs(UnmanagedType.U1)] + public char LastChar; + + /// + /// The integer length of the file when unpacked + /// + public uint RealLength; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/CFDATA.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/CFDATA.cs new file mode 100644 index 00000000..6bb21404 --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/CFDATA.cs @@ -0,0 +1,49 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + /// + /// Each CFDATA structure describes some amount of compressed data, as shown in the following + /// packet diagram. The first CFDATA structure entry for each folder is located by using the + /// field. Subsequent CFDATA structure records for this folder are + /// contiguous. + /// + /// + public sealed class CFDATA + { + /// + /// Checksum of this CFDATA structure, from the through the + /// fields. It can be set to 0 (zero) if the checksum is not supplied. + /// + public uint Checksum { get; set; } + + /// + /// Number of bytes of compressed data in this CFDATA structure record. When the + /// field is zero, this field indicates only the number of bytes that fit into this cabinet file. + /// + public ushort CompressedSize { get; set; } + + /// + /// The uncompressed size of the data in this CFDATA structure entry in bytes. When this + /// CFDATA structure entry is continued in the next cabinet file, the field will be zero, and + /// the field in the first CFDATA structure entry in the next cabinet file will report the total + /// uncompressed size of the data from both CFDATA structure blocks. + /// + public ushort UncompressedSize { get; set; } + + /// + /// If the flag is set + /// and the field value is non-zero, this field contains per-datablock application information. + /// This field is defined by the application, and it is used for application-defined purposes. + /// + public byte[]? ReservedData { get; set; } + + /// + /// The compressed data bytes, compressed by using the + /// method. When the field value is zero, these data bytes MUST be combined with the data + /// bytes from the next cabinet's first CFDATA structure entry before decompression. When the + /// field indicates that the data is not compressed, this field contains the + /// uncompressed data bytes. In this case, the and field values will be equal unless + /// this CFDATA structure entry crosses a cabinet file boundary. + /// + public byte[]? CompressedData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/CFFILE.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/CFFILE.cs new file mode 100644 index 00000000..fcf65052 --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/CFFILE.cs @@ -0,0 +1,65 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + /// + /// Each CFFILE structure contains information about one of the files stored (or at least partially + /// stored) in this cabinet, as shown in the following packet diagram.The first CFFILE structure entry in + /// each cabinet is found at the absolute offset CFHEADER.coffFiles field. CFHEADER.cFiles field + /// indicates how many of these entries are in the cabinet. The CFFILE structure entries in a cabinet + /// are ordered by iFolder field value, and then by the uoffFolderStart field value.Entries for files + /// continued from the previous cabinet will be first, and entries for files continued to the next cabinet + /// will be last. + /// + /// + public sealed class CFFILE + { + /// + /// Specifies the uncompressed size of this file, in bytes. + /// + public uint FileSize { get; set; } + + /// + /// Specifies the uncompressed offset, in bytes, of the start of this file's data. For the + /// first file in each folder, this value will usually be zero. Subsequent files in the folder will have offsets + /// that are typically the running sum of the cbFile field values. + /// + public uint FolderStartOffset { get; set; } + + /// + /// Index of the folder that contains this file's data. + /// + public FolderIndex FolderIndex { get; set; } + + /// + /// Date of this file, in the format ((year–1980) << 9)+(month << 5)+(day), where + /// month={1..12} and day = { 1..31 }. This "date" is typically considered the "last modified" date in local + /// time, but the actual definition is application-defined. + /// + public ushort Date { get; set; } + + /// + /// Time of this file, in the format (hour << 11)+(minute << 5)+(seconds/2), where + /// hour={0..23}. This "time" is typically considered the "last modified" time in local time, but the + /// actual definition is application-defined. + /// + public ushort Time { get; set; } + + /// + /// Attributes of this file; can be used in any combination. + /// + public FileAttributes Attributes { get; set; } + + /// + /// The null-terminated name of this file. Note that this string can include path + /// separator characters.The string can contain up to 256 bytes, plus the null byte. When the + /// _A_NAME_IS_UTF attribute is set, this string can be converted directly to Unicode, avoiding + /// locale-specific dependencies. When the _A_NAME_IS_UTF attribute is not set, this string is subject + /// to interpretation depending on locale. When a string that contains Unicode characters larger than + /// 0x007F is encoded in the szName field, the _A_NAME_IS_UTF attribute SHOULD be included in + /// the file's attributes. When no characters larger than 0x007F are in the name, the + /// _A_NAME_IS_UTF attribute SHOULD NOT be set. If byte values larger than 0x7F are found in + /// CFFILE.szName field, but the _A_NAME_IS_UTF attribute is not set, the characters SHOULD be + /// interpreted according to the current location. + /// + public string? Name { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/CFFOLDER.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/CFFOLDER.cs new file mode 100644 index 00000000..fd1f391c --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/CFFOLDER.cs @@ -0,0 +1,56 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + /// + /// Each CFFOLDER structure contains information about one of the folders or partial folders stored in + /// this cabinet file, as shown in the following packet diagram.The first CFFOLDER structure entry + /// immediately follows the CFHEADER structure entry. The CFHEADER.cFolders field indicates how + /// many CFFOLDER structure entries are present. + /// + /// Folders can start in one cabinet, and continue on to one or more succeeding cabinets. When the + /// cabinet file creator detects that a folder has been continued into another cabinet, it will complete + /// that folder as soon as the current file has been completely compressed.Any additional files will be + /// placed in the next folder.Generally, this means that a folder would span at most two cabinets, but it + /// could span more than two cabinets if the file is large enough. + /// + /// CFFOLDER structure entries actually refer to folder fragments, not necessarily complete folders. A + /// CFFOLDER structure is the beginning of a folder if the iFolder field value in the first file that + /// references the folder does not indicate that the folder is continued from the previous cabinet file. + /// + /// The typeCompress field can vary from one folder to the next, unless the folder is continued from a + /// previous cabinet file. + /// + /// + public sealed class CFFOLDER + { + /// + /// Specifies the absolute file offset of the first CFDATA field block for the folder. + /// + public uint CabStartOffset { get; set; } + + /// + /// Specifies the number of CFDATA structures for this folder that are actually in this cabinet. + /// A folder can continue into another cabinet and have more CFDATA structure blocks in that cabinet + /// file.A folder can start in a previous cabinet.This number represents only the CFDATA structures for + /// this folder that are at least partially recorded in this cabinet. + /// + public ushort DataCount { get; set; } + + /// + /// Indicates the compression method used for all CFDATA structure entries in this + /// folder. + /// + public CompressionType CompressionType { get; set; } + + /// + /// If the CFHEADER.flags.cfhdrRESERVE_PRESENT field is set + /// and the cbCFFolder field is non-zero, then this field contains per-folder application information. + /// This field is defined by the application, and is used for application-defined purposes. + /// + public byte[]? ReservedData { get; set; } + + /// + /// Data blocks associated with this folder + /// + public CFDATA[]? DataBlocks { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/CFHEADER.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/CFHEADER.cs new file mode 100644 index 00000000..b59a9f6d --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/CFHEADER.cs @@ -0,0 +1,150 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + /// + /// The CFHEADER structure shown in the following packet diagram provides information about this + /// cabinet (.cab) file. + /// + /// + public sealed class CFHEADER + { + /// + /// Contains the characters "M", "S", "C", and "F" (bytes 0x4D, 0x53, 0x43, + /// 0x46). This field is used to ensure that the file is a cabinet (.cab) file. + /// + public string? Signature { get; set; } + + /// + /// Reserved field; MUST be set to 0 (zero). + /// + public uint Reserved1 { get; set; } + + /// + /// Specifies the total size of the cabinet file, in bytes. + /// + public uint CabinetSize { get; set; } + + /// + /// Reserved field; MUST be set to 0 (zero). + /// + public uint Reserved2 { get; set; } + + /// + /// Specifies the absolute file offset, in bytes, of the first CFFILE field entry. + /// + public uint FilesOffset { get; set; } + + /// + /// Reserved field; MUST be set to 0 (zero). + /// + public uint Reserved3 { get; set; } + + /// + /// Specifies the minor cabinet file format version. This value MUST be set to 3 (three). + /// + public byte VersionMinor { get; set; } + + /// + /// Specifies the major cabinet file format version. This value MUST be set to 1 (one). + /// + public byte VersionMajor { get; set; } + + /// + /// Specifies the number of CFFOLDER field entries in this cabinet file. + /// + public ushort FolderCount { get; set; } + + /// + /// Specifies the number of CFFILE field entries in this cabinet file. + /// + public ushort FileCount { get; set; } + + /// + /// Specifies bit-mapped values that indicate the presence of optional data. + /// + public HeaderFlags Flags { get; set; } + + /// + /// Specifies an arbitrarily derived (random) value that binds a collection of linked cabinet files + /// together.All cabinet files in a set will contain the same setID field value.This field is used by + /// cabinet file extractors to ensure that cabinet files are not inadvertently mixed.This value has no + /// meaning in a cabinet file that is not in a set. + /// + public ushort SetID { get; set; } + + /// + /// Specifies the sequential number of this cabinet in a multicabinet set. The first cabinet has + /// iCabinet=0. This field, along with the setID field, is used by cabinet file extractors to ensure that + /// this cabinet is the correct continuation cabinet when spanning cabinet files. + /// + public ushort CabinetIndex { get; set; } + + /// + /// If the flags.cfhdrRESERVE_PRESENT field is not set, this field is not + /// present, and the value of cbCFHeader field MUST be zero.Indicates the size, in bytes, of the + /// abReserve field in this CFHEADER structure.Values for cbCFHeader field MUST be between 0- + /// 60,000. + /// + public ushort HeaderReservedSize { get; set; } + + /// + /// If the flags.cfhdrRESERVE_PRESENT field is not set, this field is not + /// present, and the value of cbCFFolder field MUST be zero.Indicates the size, in bytes, of the + /// abReserve field in each CFFOLDER field entry.Values for fhe cbCFFolder field MUST be between + /// 0-255. + /// + public byte FolderReservedSize { get; set; } + + /// + /// If the flags.cfhdrRESERVE_PRESENT field is not set, this field is not + /// present, and the value for the cbCFDATA field MUST be zero.The cbCFDATA field indicates the + /// size, in bytes, of the abReserve field in each CFDATA field entry. Values for the cbCFDATA field + /// MUST be between 0 - 255. + /// + public byte DataReservedSize { get; set; } + + /// + /// If the flags.cfhdrRESERVE_PRESENT field is set and the + /// cbCFHeader field is non-zero, this field contains per-cabinet-file application information. This field + /// is defined by the application, and is used for application-defined purposes. + /// + public byte[]? ReservedData { get; set; } + + /// + /// If the flags.cfhdrPREV_CABINET field is not set, this + /// field is not present.This is a null-terminated ASCII string that contains the file name of the + /// logically previous cabinet file. The string can contain up to 255 bytes, plus the null byte. Note that + /// this gives the name of the most recently preceding cabinet file that contains the initial instance of a + /// file entry.This might not be the immediately previous cabinet file, when the most recent file spans + /// multiple cabinet files.If searching in reverse for a specific file entry, or trying to extract a file that is + /// reported to begin in the "previous cabinet," the szCabinetPrev field would indicate the name of the + /// cabinet to examine. + /// + public string? CabinetPrev { get; set; } + + /// + /// If the flags.cfhdrPREV_CABINET field is not set, then this + /// field is not present.This is a null-terminated ASCII string that contains a descriptive name for the + /// media that contains the file named in the szCabinetPrev field, such as the text on the disk label. + /// This string can be used when prompting the user to insert a disk. The string can contain up to 255 + /// bytes, plus the null byte. + /// + public string? DiskPrev { get; set; } + + /// + /// If the flags.cfhdrNEXT_CABINET field is not set, this + /// field is not present.This is a null-terminated ASCII string that contains the file name of the next + /// cabinet file in a set. The string can contain up to 255 bytes, plus the null byte. Files that extend + /// beyond the end of the current cabinet file are continued in the named cabinet file. + /// + public string? CabinetNext { get; set; } + + /// + /// If the flags.cfhdrNEXT_CABINET field is not set, this field is + /// not present.This is a null-terminated ASCII string that contains a descriptive name for the media + /// that contains the file named in the szCabinetNext field, such as the text on the disk label. The + /// string can contain up to 255 bytes, plus the null byte. This string can be used when prompting the + /// user to insert a disk. + /// + public string? DiskNext { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/Cabinet.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/Cabinet.cs new file mode 100644 index 00000000..2fb5db8d --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/Cabinet.cs @@ -0,0 +1,27 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + /// + /// Cabinet files are compressed packages containing a + /// number of related files.The format of a cabinet file is optimized for maximum compression. Cabinet + /// files support a number of compression formats, including MSZIP, LZX, or uncompressed. This + /// document does not specify these internal compression formats. + /// + /// + public sealed class Cabinet + { + /// + /// Cabinet header + /// + public CFHEADER? Header { get; set; } + + /// + /// One or more CFFOLDER entries + /// + public CFFOLDER[]? Folders { get; set; } + + /// + /// A series of one or more cabinet file (CFFILE) entries + /// + public CFFILE[]? Files { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/Constants.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/Constants.cs new file mode 100644 index 00000000..ae9cda41 --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x4d, 0x53, 0x43, 0x46]; + + public const string SignatureString = "MSCF"; + + public const uint SignatureUInt32 = 0x4643534d; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/MicrosoftCabinet/Enums.cs b/SabreTools.Serialization/Models/MicrosoftCabinet/Enums.cs new file mode 100644 index 00000000..223a2353 --- /dev/null +++ b/SabreTools.Serialization/Models/MicrosoftCabinet/Enums.cs @@ -0,0 +1,118 @@ +using System; + +namespace SabreTools.Serialization.Models.MicrosoftCabinet +{ + public enum CompressionType : ushort + { + /// + /// Mask for compression type. + /// + MASK_TYPE = 0x000F, + + /// + /// No compression. + /// + TYPE_NONE = 0x0000, + + /// + /// MSZIP compression. + /// + TYPE_MSZIP = 0x0001, + + /// + /// Quantum compression. + /// + TYPE_QUANTUM = 0x0002, + + /// + /// LZX compression. + /// + TYPE_LZX = 0x0003, + } + + [Flags] + public enum FileAttributes : ushort + { + /// + /// File is read-only. + /// + RDONLY = 0x0001, + + /// + /// File is hidden. + /// + HIDDEN = 0x0002, + + /// + /// File is a system file. + /// + SYSTEM = 0x0004, + + /// + /// File has been modified since last backup. + /// + ARCH = 0x0040, + + /// + /// File will be run after extraction. + /// + EXEC = 0x0080, + + /// + /// The szName field contains UTF. + /// + NAME_IS_UTF = 0x0100, + } + + public enum FolderIndex : ushort + { + /// + /// A value of zero indicates that this is the + /// first folder in this cabinet file. + /// + FIRST_FOLDER = 0x0000, + + /// + /// Indicates that the folder index is actually zero, but that + /// extraction of this file would have to begin with the cabinet named in the + /// CFHEADER.szCabinetPrev field. + /// + CONTINUED_FROM_PREV = 0xFFFD, + + /// + /// Indicates that the folder index + /// is actually one less than THE CFHEADER.cFolders field value, and that extraction of this file will + /// require continuation to the cabinet named in the CFHEADER.szCabinetNext field. + /// + CONTINUED_TO_NEXT = 0xFFFE, + + /// + /// + CONTINUED_PREV_AND_NEXT = 0xFFFF, + } + + [Flags] + public enum HeaderFlags : ushort + { + /// + /// The flag is set if this cabinet file is not the first in a set of cabinet files. + /// When this bit is set, the szCabinetPrev and szDiskPrev fields are present in this CFHEADER + /// structure. The value is 0x0001. + /// + PREV_CABINET = 0x0001, + + /// + /// The flag is set if this cabinet file is not the last in a set of cabinet files. + /// When this bit is set, the szCabinetNext and szDiskNext fields are present in this CFHEADER + /// structure. The value is 0x0002. + /// + NEXT_CABINET = 0x0002, + + /// + /// The flag is set if if this cabinet file contains any reserved fields. When + /// this bit is set, the cbCFHeader, cbCFFolder, and cbCFData fields are present in this CFHEADER + /// structure. The value is 0x0004. + /// + RESERVE_PRESENT = 0x0004, + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/Archive.cs b/SabreTools.Serialization/Models/MoPaQ/Archive.cs new file mode 100644 index 00000000..43a9420b --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/Archive.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// MPQ (MoPaQ) is an archive format developed by Blizzard Entertainment, + /// purposed for storing data files, images, sounds, music and videos for + /// their games. The name MoPaQ comes from the author of the format, + /// Mike O'Brien (Mike O'brien PaCK). + /// + /// + public sealed class Archive + { + // TODO: Data before archive, ignored + + /// + /// MPQ User Data (optional) + /// + public UserData? UserData { get; set; } + + /// + /// MPQ Header (required) + /// + public ArchiveHeader? ArchiveHeader { get; set; } + + // TODO: Files (optional) + // TODO: Special files (optional) + + /// + /// HET Table (optional) + /// + public HetTable? HetTable { get; set; } + + /// + /// BET Table (optional) + /// + public BetTable? BetTable { get; set; } + + /// + /// Hash Table (optional) + /// + public HashEntry[]? HashTable { get; set; } + + /// + /// Block Table (optional) + /// + public BlockEntry[]? BlockTable { get; set; } + + /// + /// Hi-Block Table (optional) + /// + /// + /// Since World of Warcraft - The Burning Crusade, Blizzard extended + /// the MPQ format to support archives larger than 4GB. The hi-block + /// table holds the higher 16-bits of the file position in the MPQ. + /// Hi-block table is plain array of 16-bit values. This table is + /// not encrypted. + /// + public short[]? HiBlockTable { get; set; } + + // TODO: Strong digital signature + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/ArchiveHeader.cs b/SabreTools.Serialization/Models/MoPaQ/ArchiveHeader.cs new file mode 100644 index 00000000..d2bf2663 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/ArchiveHeader.cs @@ -0,0 +1,177 @@ +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// MoPaQ archive header + /// + /// + public sealed class ArchiveHeader + { + #region V1 Properties + + /// + /// The MPQ archive signature + /// + public string? Signature { get; set; } + + /// + /// Size of the archive header + /// + public uint HeaderSize { get; set; } + + /// + /// Size of MPQ archive + /// + /// + /// This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive + /// is calculated as the size from the beginning of the archive to the end of the hash table, + /// block table, or extended block table (whichever is largest). + /// + public uint ArchiveSize { get; set; } + + /// + /// 0 = Format 1 (up to The Burning Crusade) + /// 1 = Format 2 (The Burning Crusade and newer) + /// 2 = Format 3 (WoW - Cataclysm beta or newer) + /// 3 = Format 4 (WoW - Cataclysm beta or newer) + /// + public FormatVersion FormatVersion { get; set; } + + /// + /// Power of two exponent specifying the number of 512-byte disk sectors in each logical sector + /// in the archive. The size of each logical sector in the archive is 512 * 2 ^ BlockSize. + /// + public ushort BlockSize { get; set; } + + /// + /// Offset to the beginning of the hash table, relative to the beginning of the archive. + /// + public uint HashTablePosition { get; set; } + + /// + /// Offset to the beginning of the block table, relative to the beginning of the archive. + /// + public uint BlockTablePosition { get; set; } + + /// + /// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for + /// the original MoPaQ format, or less than 2^20 for the Burning Crusade format. + /// + public uint HashTableSize { get; set; } + + /// + /// Number of entries in the block table + /// + public uint BlockTableSize { get; set; } + + #endregion + + #region V2 Properties + + /// + /// Offset to the beginning of array of 16-bit high parts of file offsets. + /// + public ulong HiBlockTablePosition { get; set; } + + /// + /// High 16 bits of the hash table offset for large archives. + /// + public ushort HashTablePositionHi { get; set; } + + /// + /// High 16 bits of the block table offset for large archives. + /// + public ushort BlockTablePositionHi { get; set; } + + #endregion + + #region V3 Properties + + /// + /// 64-bit version of the archive size + /// + public ulong ArchiveSizeLong { get; set; } + + /// + /// 64-bit position of the BET table + /// + public ulong BetTablePosition { get; set; } + + /// + /// 64-bit position of the HET table + /// + public ulong HetTablePosition { get; set; } + + #endregion + + #region V4 Properties + + /// + /// Compressed size of the hash table + /// + public ulong HashTableSizeLong { get; set; } + + /// + /// Compressed size of the block table + /// + public ulong BlockTableSizeLong { get; set; } + + /// + /// Compressed size of the hi-block table + /// + public ulong HiBlockTableSize { get; set; } + + /// + /// Compressed size of the HET block + /// + public ulong HetTableSize { get; set; } + + /// + /// Compressed size of the BET block + /// + public ulong BetTableSize { get; set; } + + /// + /// Size of raw data chunk to calculate MD5. + /// + /// MD5 of each data chunk follows the raw file data. + public uint RawChunkSize { get; set; } + + /// + /// MD5 of the block table before decryption + /// + /// 0x10 bytes + public byte[]? BlockTableMD5 { get; set; } + + /// + /// MD5 of the hash table before decryption + /// + /// 0x10 bytes + public byte[]? HashTableMD5 { get; set; } + + /// + /// MD5 of the hi-block table + /// + /// 0x10 bytes + public byte[]? HiBlockTableMD5 { get; set; } + + /// + /// MD5 of the BET table before decryption + /// + /// 0x10 bytes + public byte[]? BetTableMD5 { get; set; } + + /// + /// MD5 of the HET table before decryption + /// + /// 0x10 bytes + public byte[]? HetTableMD5 { get; set; } + + /// + /// MD5 of the MPQ header from signature to (including) HetTableMD5 + /// + /// 0x10 bytes + public byte[]? MpqHeaderMD5 { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/BetTable.cs b/SabreTools.Serialization/Models/MoPaQ/BetTable.cs new file mode 100644 index 00000000..e8dafd31 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/BetTable.cs @@ -0,0 +1,140 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// The BET table is present if the BetTablePos64 member of MPQ header is set + /// to nonzero. BET table is a successor of classic block table, and can fully + /// replace it. It is also supposed to be more effective. + /// + /// + public sealed class BetTable + { + // TODO: Extract this out and make in common between HET and BET + #region Common Table Headers + + /// + /// 'BET\x1A' + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Version. Seems to be always 1 + /// + public uint Version { get; set; } + + /// + /// Size of the contained table + /// + public uint DataSize { get; set; } + + #endregion + + /// + /// Size of the entire hash table, including the header (in bytes) + /// + public uint TableSize { get; set; } + + /// + /// Number of files in the BET table + /// + public uint FileCount { get; set; } + + /// + /// Unknown, set to 0x10 + /// + public uint Unknown { get; set; } + + /// + /// Size of one table entry (in bits) + /// + public uint TableEntrySize { get; set; } + + /// + /// Bit index of the file position (within the entry record) + /// + public uint FilePositionBitIndex { get; set; } + + /// + /// Bit index of the file size (within the entry record) + /// + public uint FileSizeBitIndex { get; set; } + + /// + /// Bit index of the compressed size (within the entry record) + /// + public uint CompressedSizeBitIndex { get; set; } + + /// + /// Bit index of the flag index (within the entry record) + /// + public uint FlagIndexBitIndex { get; set; } + + /// + /// Bit index of the ??? (within the entry record) + /// + public uint UnknownBitIndex { get; set; } + + /// + /// Bit size of file position (in the entry record) + /// + public uint FilePositionBitCount { get; set; } + + /// + /// Bit size of file size (in the entry record) + /// + public uint FileSizeBitCount { get; set; } + + /// + /// Bit size of compressed file size (in the entry record) + /// + public uint CompressedSizeBitCount { get; set; } + + /// + /// Bit size of flags index (in the entry record) + /// + public uint FlagIndexBitCount { get; set; } + + /// + /// Bit size of ??? (in the entry record) + /// + public uint UnknownBitCount { get; set; } + + /// + /// Total size of the BET hash + /// + public uint TotalBetHashSize { get; set; } + + /// + /// Extra bits in the BET hash + /// + public uint BetHashSizeExtra { get; set; } + + /// + /// Effective size of BET hash (in bits) + /// + public uint BetHashSize { get; set; } + + /// + /// Size of BET hashes array, in bytes + /// + public uint BetHashArraySize { get; set; } + + /// + /// Number of flags in the following array + /// + public uint FlagCount { get; set; } + + /// + /// Followed by array of file flags. Each entry is 32-bit size and its meaning is the same like + /// + /// Size from + public uint[]? FlagsArray { get; set; } + + // File table. Size of each entry is taken from dwTableEntrySize. + // Size of the table is (dwTableEntrySize * dwMaxFileCount), round up to 8. + + // Array of BET hashes. Table size is taken from dwMaxFileCount from HET table + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/BlockEntry.cs b/SabreTools.Serialization/Models/MoPaQ/BlockEntry.cs new file mode 100644 index 00000000..e9633588 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/BlockEntry.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// Block table contains informations about file sizes and way of their storage within + /// the archive. It also contains the position of file content in the archive. Size + /// of block table entry is (like hash table entry). The block table is also encrypted. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class BlockEntry + { + /// + /// Offset of the beginning of the file data, relative to the beginning of the archive. + /// + public uint FilePosition; + + /// + /// Compressed file size + /// + public uint CompressedSize; + + /// + /// Size of uncompressed file + /// + public uint UncompressedSize; + + /// + /// Flags for the file. + /// + [MarshalAs(UnmanagedType.U4)] + public FileFlags Flags; + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/Constants.cs b/SabreTools.Serialization/Models/MoPaQ/Constants.cs new file mode 100644 index 00000000..dd406fad --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/Constants.cs @@ -0,0 +1,83 @@ +namespace SabreTools.Serialization.Models.MoPaQ +{ + public static class Constants + { + #region Archive Header + + public static readonly byte[] ArchiveHeaderSignatureBytes = [0x4d, 0x50, 0x51, 0x1a]; + + public static readonly string ArchiveHeaderSignatureString = System.Text.Encoding.ASCII.GetString(ArchiveHeaderSignatureBytes); + + public const uint ArchiveHeaderSignatureUInt32 = 0x1a51504d; + + #endregion + + #region User Data + + public static readonly byte[] UserDataSignatureBytes = [0x4d, 0x50, 0x51, 0x1b]; + + public static readonly string UserDataSignatureString = System.Text.Encoding.ASCII.GetString(UserDataSignatureBytes); + + public const uint UserDataSignatureUInt32 = 0x1b51504d; + + #endregion + + #region HET Table + + public static readonly byte[] HetTableSignatureBytes = [0x48, 0x45, 0x54, 0x1a]; + + public static readonly string HetTableSignatureString = System.Text.Encoding.ASCII.GetString(HetTableSignatureBytes); + + public const uint HetTableSignatureUInt32 = 0x1a544548; + + #endregion + + #region BET Table + + public static readonly byte[] BetTableSignatureBytes = [0x42, 0x45, 0x54, 0x1a]; + + public static readonly string BetTableSignatureString = System.Text.Encoding.ASCII.GetString(BetTableSignatureBytes); + + public const uint BetTableSignatureUInt32 = 0x1a544542; + + #endregion + + #region Patch Header + + /// + /// Signature as an unsigned Int32 value + /// + public const uint PatchSignatureValue = 0x48435450; + + /// + /// Signature as an unsigned Int32 value + /// + public const uint Md5SignatureValue = 0x5F35444D; + + /// + /// Signature as an unsigned Int32 value + /// + public const uint XFRMSignatureValue = 0x4D524658; + + /// + /// Signature as an unsigned Int64 value + /// + public const ulong BSDIFF40SignatureValue = 0x3034464649445342; + + #endregion + + #region Encryption + + /// + /// Obtained by HashString("(block table)", MPQ_HASH_FILE_KEY) + /// + public const uint MPQ_KEY_BLOCK_TABLE = 0xEC83B3A3; + + /// + /// Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY) + /// + public const uint MPQ_KEY_HASH_TABLE = 0xC3AF3770; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/MoPaQ/Enums.cs b/SabreTools.Serialization/Models/MoPaQ/Enums.cs new file mode 100644 index 00000000..2fd0c6c5 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/Enums.cs @@ -0,0 +1,181 @@ +using System; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// Compression types for multiple compressions + /// + [Flags] + public enum CompressionType : uint + { + /// + /// Huffmann compression (used on WAVE files only) + /// + MPQ_COMPRESSION_HUFFMANN = 0x01, + + /// + /// ZLIB compression + /// + MPQ_COMPRESSION_ZLIB = 0x02, + + /// + /// PKWARE DCL compression + /// + MPQ_COMPRESSION_PKWARE = 0x08, + + /// + /// BZIP2 compression (added in Warcraft III) + /// + MPQ_COMPRESSION_BZIP2 = 0x10, + + /// + /// Sparse compression (added in Starcraft 2) + /// + MPQ_COMPRESSION_SPARSE = 0x20, + + /// + /// IMA ADPCM compression (mono) + /// + MPQ_COMPRESSION_ADPCM_MONO = 0x40, + + /// + /// IMA ADPCM compression (stereo) + /// + MPQ_COMPRESSION_ADPCM_STEREO = 0x80, + + /// + /// LZMA compression. Added in Starcraft 2. This value is NOT a combination of flags. + /// + MPQ_COMPRESSION_LZMA = 0x12, + + /// + /// Same compression + /// + MPQ_COMPRESSION_NEXT_SAME = 0xFFFFFFFF, + } + + [Flags] + public enum FileFlags : uint + { + /// + /// File is compressed using PKWARE Data compression library + /// + MPQ_FILE_IMPLODE = 0x00000100, + + /// + /// File is compressed using combination of compression methods + /// + MPQ_FILE_COMPRESS = 0x00000200, + + /// + /// The file is encrypted + /// + MPQ_FILE_ENCRYPTED = 0x00010000, + + /// + /// The decryption key for the file is altered according to the + /// position of the file in the archive + /// + MPQ_FILE_FIX_KEY = 0x00020000, + + /// + /// The file contains incremental patch for an existing file in base MPQ + /// + MPQ_FILE_PATCH_FILE = 0x00100000, + + /// + /// Instead of being divided to 0x1000-bytes blocks, the file is stored + /// as single unit + /// + MPQ_FILE_SINGLE_UNIT = 0x01000000, + + /// + /// File is a deletion marker, indicating that the file no longer exists. + /// This is used to allow patch archives to delete files present in + /// lower-priority archives in the search chain. The file usually has + /// length of 0 or 1 byte and its name is a hash + /// + MPQ_FILE_DELETE_MARKER = 0x02000000, + + /// + /// File has checksums for each sector (explained in the File Data section). + /// Ignored if file is not compressed or imploded. + /// + MPQ_FILE_SECTOR_CRC = 0x04000000, + + /// + /// Set if file exists, reset when the file was deleted + /// + MPQ_FILE_EXISTS = 0x80000000, + } + + public enum FormatVersion : ushort + { + /// + /// Format 1 (up to The Burning Crusade) + /// + Format1 = 0, + + /// + /// Format 2 (The Burning Crusade and newer) + /// + Format2 = 1, + + /// + /// Format 3 (WoW - Cataclysm beta or newer) + /// + Format3 = 2, + + /// + /// Format 4 (WoW - Cataclysm beta or newer) + /// + Format4 = 3, + } + + public enum Locale : short + { + Neutral = 0, + AmericanEnglish = 0, + ChineseTaiwan = 0x404, + Czech = 0x405, + German = 0x407, + English = 0x409, + Spanish = 0x40A, + French = 0x40C, + Italian = 0x410, + Japanese = 0x411, + Korean = 0x412, + Polish = 0x415, + Portuguese = 0x416, + Russian = 0x419, + EnglishUK = 0x809, + } + + public enum PatchType : uint + { + /// + /// Blizzard-modified version of BSDIFF40 incremental patch + /// + BSD0 = 0x30445342, + + /// + /// Unknown + /// + BSDP = 0x50445342, + + /// + /// Plain replace + /// + COPY = 0x59504F43, + + /// + /// Unknown + /// + COUP = 0x50554F43, + + /// + /// Unknown + /// + CPOG = 0x474F5043, + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/HashEntry.cs b/SabreTools.Serialization/Models/MoPaQ/HashEntry.cs new file mode 100644 index 00000000..2917a7ab --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/HashEntry.cs @@ -0,0 +1,49 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// Hash table is used for searching files by name. The file name is converted to + /// two 32-bit hash values, which are then used for searching in the table. The size + /// of the hash table must always be a power of two. Each entry in the hash table + /// also contains file locale and offset into block table. Size of one entry of hash + /// table is 16 bytes. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class HashEntry + { + /// + /// The hash of the full file name (part A) + /// + public uint NameHashPartA; + + /// + /// The hash of the full file name (part B) + /// + public uint NameHashPartB; + + /// + /// The language of the file. This is a Windows LANGID data type, and uses the same values. + /// 0 indicates the default language (American English), or that the file is language-neutral. + /// + [MarshalAs(UnmanagedType.I2)] + public Locale Locale; + + /// + /// The platform the file is used for. 0 indicates the default platform. + /// No other values have been observed. + /// + public ushort Platform; + + /// + /// If the hash table entry is valid, this is the index into the block table of the file. + /// Otherwise, one of the following two values: + /// - FFFFFFFFh: Hash table entry is empty, and has always been empty. + /// Terminates searches for a given file. + /// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file). + /// Does not terminate searches for a given file. + /// + public uint BlockIndex; + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/HetTable.cs b/SabreTools.Serialization/Models/MoPaQ/HetTable.cs new file mode 100644 index 00000000..1f465868 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/HetTable.cs @@ -0,0 +1,87 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// The HET table is present if the HetTablePos64 member of MPQ header is + /// set to nonzero. This table can fully replace hash table. Depending on + /// MPQ size, the pair of HET&BET table can be more efficient than Hash&Block + /// table. HET table can be encrypted and compressed. + /// + /// + public sealed class HetTable + { + // TODO: Extract this out and make in common between HET and BET + #region Common Table Headers + + /// + /// 'HET\x1A' + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Version. Seems to be always 1 + /// + public uint Version { get; set; } + + /// + /// Size of the contained table + /// + public uint DataSize { get; set; } + + #endregion + + /// + /// Size of the entire hash table, including the header (in bytes) + /// + public uint TableSize { get; set; } + + /// + /// Maximum number of files in the MPQ + /// + public uint MaxFileCount { get; set; } + + /// + /// Size of the hash table (in bytes) + /// + public uint HashTableSize { get; set; } + + /// + /// Effective size of the hash entry (in bits) + /// + public uint HashEntrySize { get; set; } + + /// + /// Total size of file index (in bits) + /// + public uint TotalIndexSize { get; set; } + + /// + /// Extra bits in the file index + /// + public uint IndexSizeExtra { get; set; } + + /// + /// Effective size of the file index (in bits) + /// + public uint IndexSize { get; set; } + + /// + /// Size of the block index subtable (in bytes) + /// + public uint BlockTableSize { get; set; } + + /// + /// HET hash table. Each entry is 8 bits. + /// + /// Size is derived from HashTableSize + public byte[]? HashTable { get; set; } + + /// + /// Array of file indexes. Bit size of each entry is taken from dwTotalIndexSize. + /// Table size is taken from dwHashTableSize. + /// + public byte[][]? FileIndexes { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/PatchHeader.cs b/SabreTools.Serialization/Models/MoPaQ/PatchHeader.cs new file mode 100644 index 00000000..84771627 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/PatchHeader.cs @@ -0,0 +1,115 @@ +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// Each incremental patch file in a patch MPQ starts with a header. It is supposed + /// to be a structure with variable length. + /// + /// + public sealed class PatchHeader + { + #region PATCH Header + + /// + /// 'PTCH' + /// + public uint PatchSignature { get; set; } + + /// + /// Size of the entire patch (decompressed) + /// + public int SizeOfPatchData { get; set; } + + /// + /// Size of the file before patch + /// + public int SizeBeforePatch { get; set; } + + /// + /// Size of file after patch + /// + public int SizeAfterPatch { get; set; } + + #endregion + + #region MD5 Block + + /// + /// 'MD5_' + /// + public uint Md5Signature { get; set; } + + /// + /// Size of the MD5 block, including the signature and size itself + /// + public int Md5BlockSize { get; set; } + + /// + /// MD5 of the original (unpached) file + /// + public byte[]? Md5BeforePatch { get; set; } = new byte[0x10]; + + /// + /// MD5 of the patched file + /// + public byte[]? Md5AfterPatch { get; set; } = new byte[0x10]; + + #endregion + + #region XFRM Block + + /// + /// 'XFRM' + /// + public uint XfrmSignature { get; set; } + + /// + /// Size of the XFRM block, includes XFRM header and patch data + /// + public int XfrmBlockSize { get; set; } + + /// + /// Type of patch ('BSD0' or 'COPY') + /// + public PatchType PatchType { get; set; } + + #endregion + + #region Patch Data - BSD0 + + /// + /// 'BSDIFF40' signature + /// + public ulong BsdiffSignature { get; set; } + + /// + /// Size of CTRL block (in bytes) + /// + public long CtrlBlockSize { get; set; } + + /// + /// Size of DATA block (in bytes) + /// + public long DataBlockSize { get; set; } + + /// + /// Size of file after applying the patch (in bytes) + /// + public long NewFileSize { get; set; } + + // TODO: Fill rest of data from http://zezula.net/en/mpq/patchfiles.html + // CTRL block + // DATA block + // EXTRA block + + #endregion + + #region Patch Data - COPY + + /// + /// File data are simply replaced by the data in the patch. + /// + public byte[]? PatchDataCopy { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/PatchInfo.cs b/SabreTools.Serialization/Models/MoPaQ/PatchInfo.cs new file mode 100644 index 00000000..71613bd0 --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/PatchInfo.cs @@ -0,0 +1,42 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// This structure contains size of the patch, flags and also MD5 of the patch. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class PatchInfo + { + /// + /// Length of patch info header, in bytes + /// + public uint Length; + + /// + /// Flags. 0x80000000 = MD5 (?) + /// + public uint Flags; + + /// + /// Uncompressed size of the patch file + /// + public uint DataSize; + + /// + /// MD5 of the entire patch file after decompression + /// + /// 0x10 bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)] + public byte[]? MD5; + + /// + /// The sector offset table (variable length) + /// + /// 0 entries + /// TODO: Determine the number of entries + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0)] + public uint[]? SectorOffsetTable; + } +} diff --git a/SabreTools.Serialization/Models/MoPaQ/UserData.cs b/SabreTools.Serialization/Models/MoPaQ/UserData.cs new file mode 100644 index 00000000..13cee7ac --- /dev/null +++ b/SabreTools.Serialization/Models/MoPaQ/UserData.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MoPaQ +{ + /// + /// MPQ User Data are optional, and is commonly used in custom maps for + /// Starcraft II. If MPQ User Data header is present, it contains an offset, + /// from where the MPQ header should be searched. + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class UserData + { + /// + /// The user data signature + /// + /// + /// 4 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Maximum size of the user data + /// + public uint UserDataSize; + + /// + /// Offset of the MPQ header, relative to the beginning of this header + /// + public uint HeaderOffset; + + /// + /// Appears to be size of user data header (Starcraft II maps) + /// + public uint UserDataHeaderSize; + + // TODO: Does this area contain extra data that should be read in? + } +} diff --git a/SabreTools.Serialization/Models/NCF/ChecksumEntry.cs b/SabreTools.Serialization/Models/NCF/ChecksumEntry.cs new file mode 100644 index 00000000..10066de5 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/ChecksumEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumEntry + { + /// + /// Checksum. + /// + public uint Checksum; + } +} diff --git a/SabreTools.Serialization/Models/NCF/ChecksumHeader.cs b/SabreTools.Serialization/Models/NCF/ChecksumHeader.cs new file mode 100644 index 00000000..a1ec3fe0 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/ChecksumHeader.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumHeader + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Size of LPNCFCHECKSUMHEADER & LPNCFCHECKSUMMAPHEADER & in bytes. + /// + public uint ChecksumSize; + } +} diff --git a/SabreTools.Serialization/Models/NCF/ChecksumMapEntry.cs b/SabreTools.Serialization/Models/NCF/ChecksumMapEntry.cs new file mode 100644 index 00000000..55dd7bd7 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/ChecksumMapEntry.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumMapEntry + { + /// + /// Number of checksums. + /// + public uint ChecksumCount; + + /// + /// Index of first checksum. + /// + public uint FirstChecksumIndex; + } +} diff --git a/SabreTools.Serialization/Models/NCF/ChecksumMapHeader.cs b/SabreTools.Serialization/Models/NCF/ChecksumMapHeader.cs new file mode 100644 index 00000000..d369f027 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/ChecksumMapHeader.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ChecksumMapHeader + { + /// + /// Always 0x14893721 + /// + public uint Dummy0; + + /// + /// Always 0x00000001 + /// + public uint Dummy1; + + /// + /// Number of items. + /// + public uint ItemCount; + + /// + /// Number of checksums. + /// + public uint ChecksumCount; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryCopyEntry.cs b/SabreTools.Serialization/Models/NCF/DirectoryCopyEntry.cs new file mode 100644 index 00000000..2b132192 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryCopyEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryCopyEntry + { + /// + /// Index of the directory item. + /// + public uint DirectoryIndex; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryEntry.cs b/SabreTools.Serialization/Models/NCF/DirectoryEntry.cs new file mode 100644 index 00000000..de355414 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryEntry.cs @@ -0,0 +1,45 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryEntry + { + /// + /// Offset to the directory item name from the end of the directory items. + /// + public uint NameOffset; + + /// + /// Size of the item. (If file, file size. If folder, num items.) + /// + public uint ItemSize; + + /// + /// Checksome index. (0xFFFFFFFF == None). + /// + public uint ChecksumIndex; + + /// + /// Flags for the directory item. (0x00000000 == Folder). + /// + [MarshalAs(UnmanagedType.U4)] + public HL_NCF_FLAG DirectoryFlags; + + /// + /// Index of the parent directory item. (0xFFFFFFFF == None). + /// + public uint ParentIndex; + + /// + /// Index of the next directory item. (0x00000000 == None). + /// + public uint NextIndex; + + /// + /// Index of the first directory item. (0x00000000 == None). + /// + public uint FirstIndex; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryHeader.cs b/SabreTools.Serialization/Models/NCF/DirectoryHeader.cs new file mode 100644 index 00000000..715ffb61 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryHeader.cs @@ -0,0 +1,79 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryHeader + { + /// + /// Always 0x00000004 + /// + public uint Dummy0; + + /// + /// Cache ID. + /// + public uint CacheID; + + /// + /// NCF file version. + /// + public uint LastVersionPlayed; + + /// + /// Number of items in the directory. + /// + public uint ItemCount; + + /// + /// Number of files in the directory. + /// + public uint FileCount; + + /// + /// Always 0x00008000. Data per checksum? + /// + public uint ChecksumDataLength; + + /// + /// Size of lpNCFDirectoryEntries & lpNCFDirectoryNames & lpNCFDirectoryInfo1Entries & lpNCFDirectoryInfo2Entries & lpNCFDirectoryCopyEntries & lpNCFDirectoryLocalEntries in bytes. + /// + public uint DirectorySize; + + /// + /// Size of the directory names in bytes. + /// + public uint NameSize; + + /// + /// Number of Info1 entires. + /// + public uint Info1Count; + + /// + /// Number of files to copy. + /// + public uint CopyCount; + + /// + /// Number of files to keep local. + /// + public uint LocalCount; + + /// + /// Reserved + /// + public uint Dummy1; + + /// + /// Reserved + /// + public uint Dummy2; + + /// + /// Header checksum. + /// + public uint Checksum; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryInfo1Entry.cs b/SabreTools.Serialization/Models/NCF/DirectoryInfo1Entry.cs new file mode 100644 index 00000000..acd34a0a --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryInfo1Entry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryInfo1Entry + { + /// + /// Reserved + /// + public uint Dummy0; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryInfo2Entry.cs b/SabreTools.Serialization/Models/NCF/DirectoryInfo2Entry.cs new file mode 100644 index 00000000..dbb941ea --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryInfo2Entry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryInfo2Entry + { + /// + /// Reserved + /// + public uint Dummy0; + } +} diff --git a/SabreTools.Serialization/Models/NCF/DirectoryLocalEntry.cs b/SabreTools.Serialization/Models/NCF/DirectoryLocalEntry.cs new file mode 100644 index 00000000..363841cf --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/DirectoryLocalEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryLocalEntry + { + /// + /// Index of the directory item. + /// + public uint DirectoryIndex; + } +} diff --git a/SabreTools.Serialization/Models/NCF/Enums.cs b/SabreTools.Serialization/Models/NCF/Enums.cs new file mode 100644 index 00000000..d9151e96 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/Enums.cs @@ -0,0 +1,38 @@ +using System; + +namespace SabreTools.Serialization.Models.NCF +{ + [Flags] + public enum HL_NCF_FLAG : uint + { + /// + /// Folder + /// + HL_NCF_FLAG_FOLDER = 0x00000000, + + /// + /// Don't overwrite the item if copying it to the disk and the item already exis + /// + HL_NCF_FLAG_COPY_LOCAL_NO_OVERWRITE = 0x00000001, + + /// + /// The item is to be copied to the disk. + /// + HL_NCF_FLAG_COPY_LOCAL = 0x0000000a, + + /// + /// Backup the item before overwriting it. + /// + HL_NCF_FLAG_BACKUP_LOCAL = 0x00000040, + + /// + /// The item is encrypted. + /// + HL_NCF_FLAG_ENCRYPTED = 0x00000100, + + /// + /// The item is a file. + /// + HL_NCF_FLAG_FILE = 0x00004000, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/NCF/File.cs b/SabreTools.Serialization/Models/NCF/File.cs new file mode 100644 index 00000000..c9609761 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/File.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + /// Half-Life No Cache File + /// + /// + public sealed class File + { + /// + /// Header data + /// + public Header? Header { get; set; } + + /// + /// Directory header data + /// + public DirectoryHeader? DirectoryHeader { get; set; } + + /// + /// Directory entries data + /// + public DirectoryEntry[]? DirectoryEntries { get; set; } + + /// + /// Directory names data + /// + public Dictionary? DirectoryNames { get; set; } + + /// + /// Directory info 1 entries data + /// + public DirectoryInfo1Entry[]? DirectoryInfo1Entries { get; set; } + + /// + /// Directory info 2 entries data + /// + public DirectoryInfo2Entry[]? DirectoryInfo2Entries { get; set; } + + /// + /// Directory copy entries data + /// + public DirectoryCopyEntry[]? DirectoryCopyEntries { get; set; } + + /// + /// Directory local entries data + /// + public DirectoryLocalEntry[]? DirectoryLocalEntries { get; set; } + + /// + /// Unknown header data + /// + public UnknownHeader? UnknownHeader { get; set; } + + /// + /// Unknown entries data + /// + public UnknownEntry[]? UnknownEntries { get; set; } + + /// + /// Checksum header data + /// + public ChecksumHeader? ChecksumHeader { get; set; } + + /// + /// Checksum map header data + /// + public ChecksumMapHeader? ChecksumMapHeader { get; set; } + + /// + /// Checksum map entries data + /// + public ChecksumMapEntry[]? ChecksumMapEntries { get; set; } + + /// + /// Checksum entries data + /// + public ChecksumEntry[]? ChecksumEntries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NCF/Header.cs b/SabreTools.Serialization/Models/NCF/Header.cs new file mode 100644 index 00000000..5f95a088 --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/Header.cs @@ -0,0 +1,64 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Header + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Always 0x00000002 + /// + public uint MajorVersion; + + /// + /// NCF version number. + /// + public uint MinorVersion; + + /// + /// Cache ID + /// + public uint CacheID; + + /// + /// Last version played + /// + public uint LastVersionPlayed; + + /// + /// Reserved + /// + public uint Dummy1; + + /// + /// Reserved + /// + public uint Dummy2; + + /// + /// Total size of NCF file in bytes. + /// + public uint FileSize; + + /// + /// Size of each data block in bytes. + /// + public uint BlockSize; + + /// + /// Number of data blocks. + /// + public uint BlockCount; + + /// + /// Reserved + /// + public uint Dummy3; + } +} diff --git a/SabreTools.Serialization/Models/NCF/UnknownEntry.cs b/SabreTools.Serialization/Models/NCF/UnknownEntry.cs new file mode 100644 index 00000000..16d9629b --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/UnknownEntry.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class UnknownEntry + { + /// + /// Reserved + /// + public uint Dummy0; + } +} diff --git a/SabreTools.Serialization/Models/NCF/UnknownHeader.cs b/SabreTools.Serialization/Models/NCF/UnknownHeader.cs new file mode 100644 index 00000000..127575fb --- /dev/null +++ b/SabreTools.Serialization/Models/NCF/UnknownHeader.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NCF +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class UnknownHeader + { + /// + /// Always 0x00000001 + /// + public uint Dummy0; + + /// + /// Always 0x00000000 + /// + public uint Dummy1; + } +} diff --git a/SabreTools.Serialization/Models/PAK/Constants.cs b/SabreTools.Serialization/Models/PAK/Constants.cs new file mode 100644 index 00000000..c2ea3866 --- /dev/null +++ b/SabreTools.Serialization/Models/PAK/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.PAK +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x50, 0x41, 0x43, 0x4b]; + + public const string SignatureString = "PACK"; + + public const uint SignatureUInt32 = 0x4b434150; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PAK/DirectoryItem.cs b/SabreTools.Serialization/Models/PAK/DirectoryItem.cs new file mode 100644 index 00000000..503d7ca4 --- /dev/null +++ b/SabreTools.Serialization/Models/PAK/DirectoryItem.cs @@ -0,0 +1,25 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PAK +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class DirectoryItem + { + /// + /// Item Name + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)] + public string? ItemName; + + /// + /// Item Offset + /// + public uint ItemOffset; + + /// + /// Item Length + /// + public uint ItemLength; + } +} diff --git a/SabreTools.Serialization/Models/PAK/File.cs b/SabreTools.Serialization/Models/PAK/File.cs new file mode 100644 index 00000000..a2c36ab0 --- /dev/null +++ b/SabreTools.Serialization/Models/PAK/File.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.PAK +{ + /// + /// Half-Life Package File + /// + /// + public sealed class File + { + /// + /// Deserialized directory header data + /// + public Header? Header { get; set; } + + /// + /// Deserialized directory items data + /// + public DirectoryItem[]? DirectoryItems { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PAK/Header.cs b/SabreTools.Serialization/Models/PAK/Header.cs new file mode 100644 index 00000000..3fc014e4 --- /dev/null +++ b/SabreTools.Serialization/Models/PAK/Header.cs @@ -0,0 +1,25 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PAK +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// Signature + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Directory Offset + /// + public uint DirectoryOffset; + + /// + /// Directory Length + /// + public uint DirectoryLength; + } +} diff --git a/SabreTools.Serialization/Models/PFF/Archive.cs b/SabreTools.Serialization/Models/PFF/Archive.cs new file mode 100644 index 00000000..5276fe9f --- /dev/null +++ b/SabreTools.Serialization/Models/PFF/Archive.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.PFF +{ + /// + /// PFF archive + /// + /// + public sealed class Archive + { + /// + /// Archive header + /// + public Header? Header { get; set; } + + /// + /// Segments + /// + public Segment[]? Segments { get; set; } + + /// + /// Footer + /// + public Footer? Footer { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PFF/Constants.cs b/SabreTools.Serialization/Models/PFF/Constants.cs new file mode 100644 index 00000000..5a06227e --- /dev/null +++ b/SabreTools.Serialization/Models/PFF/Constants.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.PFF +{ + /// + public static class Constants + { + public static readonly byte[] Version0SignatureBytes = [0x50, 0x46, 0x46, 0x30]; + + public const string Version0SignatureString = "PFF0"; + + public const uint Version0HSegmentSize = 0x00000020; + + // Version 1 not confirmed + // public const string Version1SignatureString = "PFF1"; + // public const uint Version1SegmentSize = 0x00000020; + + public static readonly byte[] Version2SignatureBytes = [0x50, 0x46, 0x46, 0x32]; + + public const string Version2SignatureString = "PFF2"; + + public const uint Version2SegmentSize = 0x00000020; + + public static readonly byte[] Version3SignatureBytes = [0x50, 0x46, 0x46, 0x33]; + + public const string Version3SignatureString = "PFF3"; + + public const uint Version3SegmentSize = 0x00000024; + + public static readonly byte[] Version4SignatureBytes = [0x50, 0x46, 0x46, 0x34]; + + public const string Version4SignatureString = "PFF4"; + + public const uint Version4SegmentSize = 0x00000028; + + public const string FooterKingTag = "KING"; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PFF/Footer.cs b/SabreTools.Serialization/Models/PFF/Footer.cs new file mode 100644 index 00000000..bf8951df --- /dev/null +++ b/SabreTools.Serialization/Models/PFF/Footer.cs @@ -0,0 +1,28 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PFF +{ + /// + /// PFF file footer + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Footer + { + /// + /// Current system IP + /// + public uint SystemIP; + + /// + /// Reserved + /// + public uint Reserved; + + /// + /// King tag + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? KingTag; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PFF/Header.cs b/SabreTools.Serialization/Models/PFF/Header.cs new file mode 100644 index 00000000..abbbd4ab --- /dev/null +++ b/SabreTools.Serialization/Models/PFF/Header.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PFF +{ + /// + /// PFF archive header + /// + /// Versions 2, 3, and 4 supported + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// Size of the following header + /// + public uint HeaderSize; + + /// + /// Signature + /// + /// Versions 2 and 3 share the same signature but different header sizes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Number of files + /// + public uint NumberOfFiles; + + /// + /// File segment size + /// + public uint FileSegmentSize; + + /// + /// File list offset + /// + public uint FileListOffset; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PFF/Segment.cs b/SabreTools.Serialization/Models/PFF/Segment.cs new file mode 100644 index 00000000..11f43a2d --- /dev/null +++ b/SabreTools.Serialization/Models/PFF/Segment.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.PFF +{ + /// + /// PFF segment identifier + /// + /// + public sealed class Segment + { + /// + /// Deleted flag + /// + public uint Deleted { get; set; } + + /// + /// File location + /// + public uint FileLocation { get; set; } + + /// + /// File size + /// + public uint FileSize { get; set; } + + /// + /// Packed date + /// + public uint PackedDate { get; set; } + + /// + /// File name + /// + public string? FileName { get; set; } + + /// + /// Modified date + /// + /// Only for versions 3 and 4 + public uint ModifiedDate { get; set; } + + /// + /// Compression level + /// + /// Only for version 4 + public uint CompressionLevel { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PKZIP/AS400ExtraFieldAttribute.cs b/SabreTools.Serialization/Models/PKZIP/AS400ExtraFieldAttribute.cs new file mode 100644 index 00000000..3c7f2647 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/AS400ExtraFieldAttribute.cs @@ -0,0 +1,26 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// AS/400 Extra Field (0x0065) Attribute [APPENDIX A] + /// + /// + public class AS400ExtraFieldAttribute : ExtensibleDataField + { + /// + /// Field length including length + /// + /// Big-endian + public ushort FieldLength { get; set; } + + /// + /// Field code + /// + public AS400ExtraFieldAttributeFieldCode FieldCode { get; set; } + + /// + /// Data + /// + /// Variable byte length based on field code + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/AesEncryptionStructure.cs b/SabreTools.Serialization/Models/PKZIP/AesEncryptionStructure.cs new file mode 100644 index 00000000..a1865980 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/AesEncryptionStructure.cs @@ -0,0 +1,33 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// WinZip AES encryption data + /// + /// Header ID = 0x9901 + /// + public class AesEncryptionStructure : ExtensibleDataField + { + /// + /// Compression type + /// + /// Values 0f 0x01 and 0x02 are accepted + public ushort CompressionType { get; set; } + + /// + /// Vendor ID + /// + /// Should be 0x4541 + public ushort VendorID { get; set; } + + /// + /// Unknown + /// + /// This value is unreferenced + public byte Unknown { get; set; } + + /// + /// Compression method + /// + public CompressionMethod CompressionMethod { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/Archive.cs b/SabreTools.Serialization/Models/PKZIP/Archive.cs new file mode 100644 index 00000000..7572a183 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/Archive.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Represents a single ZIP/ZIP64 archive + /// + /// PKZIP archives are meant to be read from the end + public class Archive + { + /// + /// Local file entries + /// + public LocalFile[]? LocalFiles { get; set; } + + /// + /// Optional archive decryption header, appears after all entries + /// + /// TODO: Determine the model + public byte[]? ArchiveDecryptionHeader { get; set; } + + /// + /// Optional archive extra data record, appears after either + /// the archive decryption header or after all entries + /// + public ArchiveExtraDataRecord? ArchiveExtraDataRecord { get; set; } + + /// + /// Central directory headers in sequential order + /// + public CentralDirectoryFileHeader[]? CentralDirectoryHeaders { get; set; } + + /// + /// Optional ZIP64 end of central directory record + /// + public EndOfCentralDirectoryRecord64? ZIP64EndOfCentralDirectoryRecord { get; set; } + + /// + /// Optional ZIP64 end of central directory locator + /// + public EndOfCentralDirectoryLocator64? ZIP64EndOfCentralDirectoryLocator { get; set; } + + /// + /// Required end of central directory record, always must be last + /// + public EndOfCentralDirectoryRecord? EndOfCentralDirectoryRecord { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ArchiveExtraDataRecord.cs b/SabreTools.Serialization/Models/PKZIP/ArchiveExtraDataRecord.cs new file mode 100644 index 00000000..975b7e95 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ArchiveExtraDataRecord.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Archive extra data record + /// + /// + public class ArchiveExtraDataRecord + { + /// + /// Archive extra data signature (0x08064B50) + /// + public uint Signature { get; set; } + + /// + /// Extra field length + /// + public uint ExtraFieldLength { get; set; } + + /// + /// Extra field data (variable size) + /// + public byte[]? ExtraFieldData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/CentralDirectoryFileHeader.cs b/SabreTools.Serialization/Models/PKZIP/CentralDirectoryFileHeader.cs new file mode 100644 index 00000000..63973024 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/CentralDirectoryFileHeader.cs @@ -0,0 +1,119 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Central directory file header + /// + /// + public class CentralDirectoryFileHeader + { + /// + /// Central file header signature (0x02014B50) + /// + public uint Signature { get; set; } + + /// + /// Host system on which the file attributes are compatible + /// + public HostSystem HostSystem { get; set; } + + /// + /// ZIP specification version + /// + public byte VersionMadeBy { get; set; } + + /// + /// Version needed to extract + /// + /// TODO: Add mapping of versions + public ushort VersionNeededToExtract { get; set; } + + /// + /// General purpose bit flag + /// + public GeneralPurposeBitFlags Flags { get; set; } + + /// + /// Compression method + /// + public CompressionMethod CompressionMethod { get; set; } + + /// + /// Last modified file time + /// + public ushort LastModifedFileTime { get; set; } + + /// + /// Last modified file date + /// + public ushort LastModifiedFileDate { get; set; } + + /// + /// CRC-32 + /// + public uint CRC32 { get; set; } + + /// + /// Compressed size + /// + public uint CompressedSize { get; set; } + + /// + /// Uncompressed size + /// + public uint UncompressedSize { get; set; } + + /// + /// File name length + /// + public ushort FileNameLength { get; set; } + + /// + /// Extra field length + /// + public ushort ExtraFieldLength { get; set; } + + /// + /// File comment length + /// + public ushort FileCommentLength { get; set; } + + /// + /// Disk number start + /// + public ushort DiskNumberStart { get; set; } + + /// + /// Internal file attributes + /// + public InternalFileAttributes InternalFileAttributes { get; set; } + + /// + /// External file attributes + /// + public uint ExternalFileAttributes { get; set; } + + /// + /// Relative offset of local header + /// + /// + /// If ZIP64 and value is 0xFFFFFFFF, size will be in the + /// extended information extra field + /// + public uint RelativeOffsetOfLocalHeader { get; set; } + + /// + /// File name (variable size) + /// + public string? FileName { get; set; } + + /// + /// Extra fields (variable size) + /// + public ExtensibleDataField[]? ExtraFields { get; set; } + + /// + /// File comment (variable size) + /// + public string? FileComment { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/Constants.cs b/SabreTools.Serialization/Models/PKZIP/Constants.cs new file mode 100644 index 00000000..2ce36388 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/Constants.cs @@ -0,0 +1,85 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + public static class Constants + { + #region Archive Extra Data Record + + public const uint ArchiveExtraDataRecordSignature = 0x08064B50; + + public static readonly byte[] ArchiveExtraDataRecordSignatureBytes = [0x50, 0x4B, 0x06, 0x08]; + + public static readonly string ArchiveExtraDataRecordSignatureString = "PK" + (char)0x06 + (char)0x08; + + #endregion + + #region Central Directory File Header + + public const uint CentralDirectoryFileHeaderSignature = 0x02014B50; + + public static readonly byte[] CentralDirectoryFileHeaderSignatureBytes = [0x50, 0x4B, 0x01, 0x02]; + + public static readonly string CentralDirectoryFileHeaderSignatureString = "PK" + (char)0x01 + (char)0x02; + + #endregion + + #region Data Descriptor + + public const uint DataDescriptorSignature = 0x08074B50; + + public static readonly byte[] DataDescriptorSignatureBytes = [0x50, 0x4B, 0x07, 0x08]; + + public static readonly string DataDescriptorSignatureString = "PK" + (char)0x07 + (char)0x08; + + #endregion + + #region Digital Signature + + public const uint DigitalSignatureSignature = 0x05054B50; + + public static readonly byte[] DigitalSignatureSignatureBytes = [0x50, 0x4B, 0x05, 0x05]; + + public static readonly string DigitalSignatureSignatureString = "PK" + (char)0x05 + (char)0x05; + + #endregion + + #region End of Central Directory Locator (ZIP64) + + public const uint EndOfCentralDirectoryLocator64Signature = 0x07064B50; + + public static readonly byte[] EndOfCentralDirectoryLocator64SignatureBytes = [0x50, 0x4B, 0x06, 0x07]; + + public static readonly string EndOfCentralDirectoryLocator64SignatureString = "PK" + (char)0x06 + (char)0x07; + + #endregion + + #region End of Central Directory Record + + public const uint EndOfCentralDirectoryRecordSignature = 0x06054B50; + + public static readonly byte[] EndOfCentralDirectoryRecordSignatureBytes = [0x50, 0x4B, 0x05, 0x06]; + + public static readonly string EndOfCentralDirectoryRecordSignatureString = "PK" + (char)0x05 + (char)0x06; + + #endregion + + #region End of Central Directory Record (ZIP64) + + public const uint EndOfCentralDirectoryRecord64Signature = 0x06064B50; + + public static readonly byte[] EndOfCentralDirectoryRecord64SignatureBytes = [0x50, 0x4B, 0x06, 0x06]; + + public static readonly string EndOfCentralDirectoryRecord64SignatureString = "PK" + (char)0x06 + (char)0x06; + + #endregion + + #region Local File Header + + public const uint LocalFileHeaderSignature = 0x04034B50; + + public static readonly byte[] LocalFileHeaderSignatureBytes = [0x50, 0x4B, 0x03, 0x04]; + + public static readonly string LocalFileHeaderSignatureString = "PK" + (char)0x03 + (char)0x04; + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/DataDescriptor.cs b/SabreTools.Serialization/Models/PKZIP/DataDescriptor.cs new file mode 100644 index 00000000..86812c19 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/DataDescriptor.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Data descriptor + /// + /// + public class DataDescriptor + { + /// + /// Recommended, but optional, signature (0x08074B50) + /// + public uint? Signature { get; set; } + + /// + /// CRC-32 + /// + public uint CRC32 { get; set; } + + /// + /// Compressed size + /// + public uint CompressedSize { get; set; } + + /// + /// Uncompressed size + /// + public uint UncompressedSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/DataDescriptor64.cs b/SabreTools.Serialization/Models/PKZIP/DataDescriptor64.cs new file mode 100644 index 00000000..e306c178 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/DataDescriptor64.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Data descriptor (ZIP64) + /// + /// + public class DataDescriptor64 + { + /// + /// Recommended, but optional, signature (0x08074B50) + /// + public uint? Signature { get; set; } + + /// + /// CRC-32 + /// + public uint CRC32 { get; set; } + + /// + /// Compressed size + /// + public ulong CompressedSize { get; set; } + + /// + /// Uncompressed size + /// + public ulong UncompressedSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/DataStreamAlignment.cs b/SabreTools.Serialization/Models/PKZIP/DataStreamAlignment.cs new file mode 100644 index 00000000..6020ff58 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/DataStreamAlignment.cs @@ -0,0 +1,34 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// (per Zbynek Vyskovsky) Defines alignment of data stream of this + /// entry within the zip archive. Additionally, indicates whether the + /// compression method should be kept when re-compressing the zip file. + /// + /// The purpose of this extra field is to align specific resources to + /// word or page boundaries so they can be easily mapped into memory. + /// + /// The alignment field (lower 15 bits) defines the minimal alignment + /// required by the data stream. Bit 15 of alignment field indicates + /// whether the compression method of this entry can be changed when + /// recompressing the zip file. The value 0 means the compression method + /// should not be changed. The value 1 indicates the compression method + /// may be changed. The padding field contains padding to ensure the correct + /// alignment. It can be changed at any time when the offset or required + /// alignment changes. (see https://issues.apache.org/jira/browse/COMPRESS-391) + /// + /// Header ID = 0xa11e + /// + public class DataStreamAlignment : ExtensibleDataField + { + /// + /// Required alignment and indicator + /// + public ushort Alignment { get; set; } + + /// + /// 0x00-padding + /// + public byte[]? Padding { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/DigitalSignature.cs b/SabreTools.Serialization/Models/PKZIP/DigitalSignature.cs new file mode 100644 index 00000000..3046e4bc --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/DigitalSignature.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Digital signature + /// + /// + public class DigitalSignature + { + /// + /// Header signature (0x05054B50) + /// + public uint Signature { get; set; } + + /// + /// Data length + /// + public ushort DataLength { get; set; } + + /// + /// Signature data (variable size) + /// + public byte[]? SignatureData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryLocator64.cs b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryLocator64.cs new file mode 100644 index 00000000..0df49e0e --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryLocator64.cs @@ -0,0 +1,32 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Zip64 end of central directory locator + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class EndOfCentralDirectoryLocator64 + { + /// + /// ZIP64 end of central directory locator signature (0x07064B50) + /// + public uint Signature; + + /// + /// Number of the disk with the start of the end of central directory + /// + public uint StartDiskNumber; + + /// + /// Relative offset of start of central directory record + /// + public ulong CentralDirectoryOffset; + + /// + /// Total number of disks + /// + public uint TotalDisks; + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord.cs b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord.cs new file mode 100644 index 00000000..75999a10 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord.cs @@ -0,0 +1,79 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// End of central directory record + /// + /// + public class EndOfCentralDirectoryRecord + { + /// + /// End of central directory signature (0x06054B50) + /// + public uint Signature { get; set; } + + /// + /// Number of this disk + /// + /// + /// If ZIP64 and value is 0xFFFF, size will be in the + /// extended information extra field + /// + public ushort DiskNumber { get; set; } + + /// + /// Number of the disk with the start of the central directory + /// + /// + /// If ZIP64 and value is 0xFFFF, size will be in the + /// extended information extra field + /// + public ushort StartDiskNumber { get; set; } + + /// + /// Total number of entries in the central directory on this disk + /// + /// + /// If ZIP64 and value is 0xFFFF, size will be in the + /// extended information extra field + /// + public ushort TotalEntriesOnDisk { get; set; } + + /// + /// Total number of entries in the central directory + /// + /// + /// If ZIP64 and value is 0xFFFF, size will be in the + /// extended information extra field + /// + public ushort TotalEntries { get; set; } + + /// + /// Size of the central directory + /// + /// + /// If ZIP64 and value is 0xFFFFFFFF, size will be in the + /// extended information extra field + /// + public uint CentralDirectorySize { get; set; } + + /// + /// Offset of start of central directory with respect to the + /// starting disk number + /// + /// + /// If ZIP64 and value is 0xFFFFFFFF, size will be in the + /// extended information extra field + /// + public uint CentralDirectoryOffset { get; set; } + + /// + /// .ZIP file comment length + /// + public ushort FileCommentLength { get; set; } + + /// + /// .ZIP file comment + /// + public string? FileComment { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord64.cs b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord64.cs new file mode 100644 index 00000000..375d7243 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/EndOfCentralDirectoryRecord64.cs @@ -0,0 +1,72 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Zip64 end of central directory record + /// + /// + public class EndOfCentralDirectoryRecord64 + { + /// + /// ZIP64 end of central directory signature (0x06064B50) + /// + public uint Signature { get; set; } + + /// + /// Size of ZIP64 end of central directory record + /// + /// SizeOfFixedFields + SizeOfVariableData - 12 + public ulong DirectoryRecordSize { get; set; } + + /// + /// Host system on which the file attributes are compatible + /// + public HostSystem HostSystem { get; set; } + + /// + /// ZIP specification version + /// + public byte VersionMadeBy { get; set; } + + /// + /// Version needed to extract + /// + /// TODO: Add mapping of versions + public ushort VersionNeededToExtract { get; set; } + + /// + /// Number of this disk + /// + public uint DiskNumber { get; set; } + + /// + /// Number of the disk with the start of the central directory + /// + public uint StartDiskNumber { get; set; } + + /// + /// Total number of entries in the central directory on this disk + /// + public ulong TotalEntriesOnDisk { get; set; } + + /// + /// Total number of entries in the central directory + /// + public ulong TotalEntries { get; set; } + + /// + /// Size of the central directory + /// + public ulong CentralDirectorySize { get; set; } + + /// + /// Offset of start of central directory with respect to the + /// starting disk number + /// + public ulong CentralDirectoryOffset { get; set; } + + /// + /// ZIP64 extensible data sector + /// + public byte[]? ExtensibleDataSector { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/Enums.cs b/SabreTools.Serialization/Models/PKZIP/Enums.cs new file mode 100644 index 00000000..0eb399fc --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/Enums.cs @@ -0,0 +1,1821 @@ +using System; + +/// +/// +namespace SabreTools.Serialization.Models.PKZIP +{ + [Flags] + public enum ActionsReactions : uint + { + /// + /// Use for auto detection + /// + AutoDetection = 0b0000_0000_0000_0000_0000_0000_0000_0001, + + /// + /// Treat as a self-patch + /// + SelfPatch = 0b0000_0000_0000_0000_0000_0000_0000_0010, + + /// + /// RESERVED + /// + Reserved2 = 0b0000_0000_0000_0000_0000_0000_0000_0100, + + /// + /// RESERVED + /// + Reserved3 = 0b0000_0000_0000_0000_0000_0000_0000_1000, + + /// + /// Action (None) + /// + ActionNone = 0b0000_0000_0000_0000_0000_0000_0000_0000, + + /// + /// Action (Add) + /// + ActionAdd = 0b0000_0000_0000_0000_0000_0000_0001_0000, + + /// + /// Action (Delete) + /// + ActionDelete = 0b0000_0000_0000_0000_0000_0000_0010_0000, + + /// + /// Action (Patch) + /// + ActionPatch = 0b0000_0000_0000_0000_0000_0000_0011_0000, + + /// + /// RESERVED + /// + Reserved6 = 0b0000_0000_0000_0000_0000_0000_0100_0000, + + /// + /// RESERVED + /// + Reserved7 = 0b0000_0000_0000_0000_0000_0000_1000_0000, + + /// + /// Absent file reaction (Ask) + /// + ReactionAbsentAsk = 0b0000_0000_0000_0000_0000_0000_0000_0000, + + /// + /// Absent file reaction (Skip) + /// + ReactionAbsentSkip = 0b0000_0000_0000_0000_0000_0001_0000_0000, + + /// + /// Absent file reaction (Ignore) + /// + ReactionAbsentIgnore = 0b0000_0000_0000_0000_0000_0010_0000_0000, + + /// + /// Absent file reaction (Fail) + /// + ReactionAbsentFail = 0b0000_0000_0000_0000_0000_0011_0000_0000, + + /// + /// Newer file reaction (Ask) + /// + ReactionNewerAsk = 0b0000_0000_0000_0000_0000_0000_0000_0000, + + /// + /// Newer file reaction (Skip) + /// + ReactionNewerSkip = 0b0000_0000_0000_0000_0000_0100_0000_0000, + + /// + /// Newer file reaction (Ignore) + /// + ReactionNewerIgnore = 0b0000_0000_0000_0000_0000_1000_0000_0000, + + /// + /// Newer file reaction (Fail) + /// + ReactionNewerFail = 0b0000_0000_0000_0000_0000_1100_0000_0000, + + /// + /// Unknown file reaction (Ask) + /// + ReactionUnknownAsk = 0b0000_0000_0000_0000_0000_0000_0000_0000, + + /// + /// Unknown file reaction (Skip) + /// + ReactionUnknownSkip = 0b0000_0000_0000_0000_0001_0000_0000_0000, + + /// + /// Unknown file reaction (Ignore) + /// + ReactionUnknownIgnore = 0b0000_0000_0000_0000_0010_0000_0000_0000, + + /// + /// Unknown file reaction (Fail) + /// + ReactionUnknownFail = 0b0000_0000_0000_0000_0011_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved14 = 0b0000_0000_0000_0000_0100_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved15 = 0b0000_0000_0000_0000_1000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved16 = 0b0000_0000_0000_0001_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved17 = 0b0000_0000_0000_0010_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved18 = 0b0000_0000_0000_0100_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved19 = 0b0000_0000_0000_1000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved20 = 0b0000_0000_0001_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved21 = 0b0000_0000_0010_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved22 = 0b0000_0000_0100_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved23 = 0b0000_0000_1000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved24 = 0b0000_0001_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved25 = 0b0000_0010_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved26 = 0b0000_0100_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved27 = 0b0000_1000_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved28 = 0b0001_0000_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved29 = 0b0010_0000_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved30 = 0b0100_0000_0000_0000_0000_0000_0000_0000, + + /// + /// RESERVED + /// + Reserved31 = 0b1000_0000_0000_0000_0000_0000_0000_0000, + } + + public enum AS400ExtraFieldAttributeFieldCode : ushort + { + /// + /// Source type i.e. CLP etc + /// + SourceType = 0x4001, + + /// + /// The text description of the library + /// + LibraryTextDescription = 0x4002, + + /// + /// The text description of the file + /// + FileTextDescription = 0x4003, + + /// + /// The text description of the member + /// + MemberTextDescription = 0x4004, + + /// + /// x'F0' or 0 is PF-DTA, x'F1' or 1 is PF_SRC + /// + PFType = 0x4005, + + /// + /// Database Type Code + /// + /// 1 byte + DatabaseTypeCode = 0x4007, + + /// + /// Database file and fields definition + /// + DatabaseFileAndFieldsDefinition = 0x4008, + + /// + /// GZIP file type + /// + /// 2 bytes + GZIPFileType = 0x4009, + + /// + /// IFS code page + /// + /// 2 bytes + IFSCodePage = 0x400B, + + /// + /// IFS Time of last file status change + /// + /// 4 bytes + IFSTimeOfLastFileStatusChange = 0x400C, + + /// + /// IFS Access Time + /// + /// 4 bytes + IFSAccessTime = 0x4001, + + /// + /// IFS Modification time + /// + /// 4 bytes + IFSModificationTime = 0x4001, + + /// + /// Length of the records in the file + /// + /// 2 bytes + RecordsLength = 0x4001, + + /// + /// GZIP two words + /// + /// 8 bytes + GZIPTwoWords = 0x4001, + } + + public enum CompressionMethod : ushort + { + /// + /// The file is stored (no compression) + /// + Stored = 0, + + /// + /// The file is Shrunk + /// + Shrunk = 1, + + /// + /// The file is Reduced with compression factor 1 + /// + ReducedCompressionFactor1 = 2, + + /// + /// The file is Reduced with compression factor 2 + /// + ReducedCompressionFactor2 = 3, + + /// + /// The file is Reduced with compression factor 3 + /// + ReducedCompressionFactor3 = 4, + + /// + /// The file is Reduced with compression factor 4 + /// + ReducedCompressionFactor4 = 5, + + /// + /// The file is Imploded + /// + Implode = 6, + + /// + /// Reserved for Tokenizing compression algorithm + /// + TokenizingCompressionAlgorithm = 7, + + /// + /// The file is Deflated + /// + Deflate = 8, + + /// + /// Enhanced Deflating using Deflate64(tm) + /// + Deflate64 = 9, + + /// + /// PKWARE Data Compression Library Imploding (old IBM TERSE) + /// + PKWAREDataCompressionLibraryImplode = 10, + + /// + /// Reserved by PKWARE + /// + CompressionMethod11 = 11, + + /// + /// File is compressed using BZIP2 algorithm + /// + BZIP2 = 12, + + /// + /// Reserved by PKWARE + /// + CompressionMethod13 = 13, + + /// + /// LZMA + /// + LZMA = 14, + + /// + /// Reserved by PKWARE + /// + CompressionMethod15 = 15, + + /// + /// IBM z/OS CMPSC Compression + /// + IBMzOSCMPSC = 16, + + /// + /// Reserved by PKWARE + /// + CompressionMethod17 = 17, + + /// + /// File is compressed using IBM TERSE (new) + /// + IBMTERSE = 18, + + /// + /// IBM LZ77 z Architecture + /// + IBMLZ77 = 19, + + /// + /// deprecated (use method 93 for zstd) + /// + [Obsolete] + OldZstandard = 20, + + /// + /// Zstandard (zstd) Compression + /// + Zstandard = 93, + + /// + /// MP3 Compression + /// + MP3 = 94, + + /// + /// XZ Compression + /// + XZ = 95, + + /// + /// JPEG variant + /// + JPEGVariant = 96, + + /// + /// WavPack compressed data + /// + WavPack = 97, + + /// + /// PPMd version I, Rev 1 + /// + PPMdVersionIRev1 = 98, + + /// + /// AE-x encryption marker + /// + AExEncryption = 99, + } + + [Flags] + public enum GeneralPurposeBitFlags : ushort + { + /// + /// Indicates that the file is encrypted + /// + FileEncrypted = 0b0000_0000_0000_0001, + + #region Compression Method 6 (Implode) + + /// + /// Set - 8K sliding dictionary + /// Clear - 4K sliding dictionary + /// + LargeSlidingDictionary = 0b0000_0000_0000_0010, + + /// + /// Set - 3 Shannon-Fano trees were used + /// Clear - 2 Shannon-Fano trees were used + /// + ThreeTrees = 0b0000_0000_0000_0100, + + #endregion + + #region Compression Method 8 (Deflate) + + /// + /// Normal (-en) compression + /// + NormalCompression = 0b0000_0000_0000_0000, + + /// + /// Maximum (-ex) compression + /// + MaximumCompression = 0b0000_0000_0000_0010, + + /// + /// Fast (-ef) compression + /// + FastCompression = 0b0000_0000_0000_0100, + + /// + /// Super Fast (-es) compression + /// + SuperFastCompression = 0b0000_0000_0000_0110, + + #endregion + + #region Compression Method 14 (LZMA) + + /// + /// Set - indicates an end-of-stream (EOS) marker is used to + /// mark the end of the compressed data stream. + /// Clear - an EOS marker is not present and the compressed data + /// size must be known to extract. + /// + EndOfStreamMarker = 0b0000_0000_0000_0010, + + #endregion + + /// + /// set - the fields crc-32, compressed size and + /// uncompressed size are set to zero in the + /// local header. The correct values are put + /// in the data descriptor immediately + /// following the compressed data. + /// + NoCRC = 0b0000_0000_0000_1000, + + /// + /// Reserved for use with method 8, for enhanced deflating. + /// + EnhancedDeflateReserved = 0b0000_0000_0001_0000, + + /// + /// Indicates that the file is compressed patched data. + /// + /// Requires PKZIP version 2.70 or greater + CompressedPatchedData = 0b0000_0000_0010_0000, + + /// + /// Set - you MUST set the version needed to extract value + /// to at least 50 and you MUST also set bit 0. If AES + /// encryption is used, the version needed to extract + /// value MUST be at least 51. + /// + StrongEncryption = 0b0000_0000_0100_0000, + + /// + /// Currently unused + /// + Bit7 = 0b0000_0000_1000_0000, + + /// + /// Currently unused + /// + Bit8 = 0b0000_0001_0000_0000, + + /// + /// Currently unused + /// + Bit9 = 0b0000_0010_0000_0000, + + /// + /// Currently unused + /// + Bit10 = 0b0000_0100_0000_0000, + + /// + /// Set - the filename and comment fields for this + /// file MUST be encoded using UTF-8. + /// + LanguageEncodingFlag = 0b0000_1000_0000_0000, + + /// + /// Reserved by PKWARE for enhanced compression + /// + PKWAREEnhancedCompression = 0b0001_0000_0000_0000, + + /// + /// Set - Set when encrypting the Central Directory to + /// indicate selected data values in the Local + /// Header are masked to hide their actual values + /// + LocalHeaderValuesMasked = 0b0010_0000_0000_0000, + + /// + /// Reserved by PKWARE for alternate streams + /// + PKWAREAlternateStreams = 0b0100_0000_0000_0000, + + /// + /// Reserved by PKWARE + /// + PKWAREReserved = 0b1000_0000_0000_0000, + } + + public enum HeaderID : ushort + { + /// + /// Zip64 extended information extra field + /// + Zip64ExtendedInformation = 0x0001, + + /// + /// AV Info + /// + AVInfo = 0x0007, + + /// + /// Reserved for extended language encoding data (PFS) + /// + ExtendedLanguageEncodingData = 0x0008, + + /// + /// OS/2 + /// + OS2 = 0x0009, + + /// + /// NTFS + /// + NTFS = 0x000A, + + /// + /// OpenVMS + /// + OpenVMS = 0x000C, + + /// + /// UNIX + /// + UNIX = 0x000D, + + /// + /// Reserved for file stream and fork descriptors + /// + FileStreamFork = 0x000E, + + /// + /// Patch Descriptor + /// + PatchDescriptor = 0x000F, + + /// + /// PKCS#7 Store for X.509 Certificates + /// + PKCSStore = 0x0014, + + /// + /// X.509 Certificate ID and Signature for individual file + /// + X509IndividualFile = 0x0015, + + /// + /// X.509 Certificate ID for Central Directory + /// + X509CentralDirectory = 0x0016, + + /// + /// Strong Encryption Header + /// + StrongEncryptionHeader = 0x0017, + + /// + /// Record Management Controls + /// + RecordManagementControls = 0x0018, + + /// + /// PKCS#7 Encryption Recipient Certificate List + /// + PKCSCertificateList = 0x0019, + + /// + /// Reserved for Timestamp record + /// + Timestamp = 0x0020, + + /// + /// Policy Decryption Key Record + /// + PolicyDecryptionKey = 0x0021, + + /// + /// Smartcrypt Key Provider Record + /// + SmartcryptKeyProvider = 0x0022, + + /// + /// Smartcrypt Policy Key Data Record + /// + SmartcryptPolicyKeyData = 0x0023, + + /// + /// IBM S/390 (Z390), AS/400 (I400) attributes - uncompressed + /// + IBMS390AttributesUncompressed = 0x0065, + + /// + /// Reserved for IBM S/390 (Z390), AS/400 (I400) attributes - compressed + /// + IBMS390AttributesCompressed = 0x0066, + + /// + /// POSZIP 4690 (reserved) + /// + POSZIP4690 = 0x4690, + + #region Third-Party + + /// + /// Macintosh + /// + Macintosh = 0x07C8, + + /// + /// Pixar USD header ID + /// + PixarUSD = 0x1986, + + /// + /// ZipIt Macintosh + /// + ZipItMacintosh = 0x2605, + + /// + /// ZipIt Macintosh 1.3.5+ + /// + ZipItMacintosh135Plus = 0x2705, + + /// + /// ZipIt Macintosh 1.3.5+ + /// + ZipItMacintosh135PlusAlt = 0x2805, + + /// + /// Info-ZIP Macintosh + /// + InfoZIPMacintosh = 0x334D, + + /// + /// Acorn/SparkFS + /// + AcornSparkFS = 0x4341, + + /// + /// Windows NT security descriptor (binary ACL) + /// + WindowsNTSecurityDescriptor = 0x4453, + + /// + /// VM/CMS + /// + VMCMS = 0x4704, + + /// + /// MVS + /// + MVS = 0x470F, + + /// + /// THEOS (old?) + /// + THEOSold = 0x4854, + + /// + /// FWKCS MD5 + /// + FWKCSMD5 = 0x4B46, + + /// + /// OS/2 access control list (text ACL) + /// + OS2AccessControlList = 0x4C41, + + /// + /// Info-ZIP OpenVMS + /// + InfoZIPOpenVMS = 0x4D49, + + /// + /// Macintosh Smartzip (??) + /// + MacintoshSmartzip = 0x4D63, + + /// + /// Xceed original location extra field + /// + XceedOriginalLocation = 0x4F4C, + + /// + /// AOS/VS (ACL) + /// + ADSVS = 0x5356, + + /// + /// extended timestamp + /// + ExtendedTimestamp = 0x5455, + + /// + /// Xceed unicode extra field + /// + XceedUnicode = 0x554E, + + /// + /// Info-ZIP UNIX (original, also OS/2, NT, etc) + /// + InfoZIPUNIX = 0x5855, + + /// + /// Info-ZIP Unicode Comment Extra Field + /// + InfoZIPUnicodeComment = 0x6375, + + /// + /// BeOS/BeBox + /// + BeOSBeBox = 0x6542, + + /// + /// THEOS + /// + THEOS = 0x6854, + + /// + /// Info-ZIP Unicode Path Extra Field + /// + InfoZIPUnicodePath = 0x7075, + + /// + /// AtheOS/Syllable + /// + AtheOSSyllable = 0x7441, + + /// + /// ASi UNIX + /// + ASiUNIX = 0x756E, + + /// + /// Info-ZIP UNIX (new) + /// + InfoZIPUNIXNew = 0x7855, + + /// + /// Info-ZIP UNIX (newer UID/GID) + /// + InfoZIPUNIXNewer = 0x7875, + + /// + /// Data Stream Alignment (Apache Commons-Compress) + /// + DataStreamAlignment = 0xA11E, + + /// + /// Microsoft Open Packaging Growth Hint + /// + MicrosoftOpenPackagingGrowthHint = 0xA220, + + /// + /// Java JAR file Extra Field Header ID + /// + JavaJAR = 0xCAFE, + + /// + /// Android ZIP Alignment Extra Field + /// + AndroidZIPAlignment = 0xD935, + + /// + /// Korean ZIP code page info + /// + KoreanZIPCodePage = 0xE57A, + + /// + /// SMS/QDOS + /// + SMSQDOS = 0xFD4A, + + /// + /// AE-x encryption structure + /// + AExEncryptionStructure = 0x9901, + + /// + /// Unknown + /// + Unknown = 0x9902, + + #endregion + } + + public enum HostSystem : byte + { + /// + /// MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + /// + MSDOS = 0, + + /// + /// Amiga + /// + Amiga = 1, + + /// + /// OpenVMS + /// + OpenVMS = 2, + + /// + /// UNIX + /// + UNIX = 3, + + /// + /// VM/CMS + /// + VMCMS = 4, + + /// + /// Atari ST + /// + AtariST = 5, + + /// + /// OS/2 H.P.F.S. + /// + OS2HPFS = 6, + + /// + /// Macintosh + /// + Macintosh = 7, + + /// + /// Z-System + /// + ZSystem = 8, + + /// + /// CP/M + /// + CPM = 9, + + /// + /// Windows NTFS + /// + WindowsNTFS = 10, + + /// + /// MVS (OS/390 - Z/OS) + /// + MVS = 11, + + /// + /// VSE + /// + VSE = 12, + + /// + /// Acorn Risc + /// + AcornRisc = 13, + + /// + /// VFAT + /// + VFAT = 14, + + /// + /// alternate MVS + /// + AlternateVMS = 15, + + /// + /// BeOS + /// + BeOS = 16, + + /// + /// Tandem + /// + Tandem = 17, + + /// + /// OS/400 + /// + OS400 = 18, + + /// + /// OS X (Darwin) + /// + OSX = 19, + + // 20 thru 255 - unused + } + + [Flags] + public enum InternalFileAttributes : ushort + { + /// + /// Set - The file is apparently an ASCII or text file + /// Clear - The file is apparently binary data + /// + ASCII = 0b0000_0000_0000_0001, + + /// + /// Reserved for use by PKWARE + /// + Bit1 = 0b0000_0000_0000_0010, + + /// + /// Reserved for use by PKWARE + /// + Bit2 = 0b0000_0000_0000_0100, + + /* + 4.4.14.2 The 0x0002 bit of this field indicates, if set, that + a 4 byte variable record length control field precedes each + logical record indicating the length of the record. The + record length control field is stored in little-endian byte + order. This flag is independent of text control characters, + and if used in conjunction with text data, includes any + control characters in the total length of the record. This + value is provided for mainframe data transfer support. + */ + } + + [Flags] + public enum RecordedTimeFlag : byte + { + None = 0, + + LastModified = 1, + + LastAccessed = 2, + + Created = 4, + } + + [Flags] + public enum ZipItInternalSettings : ushort + { + /// + /// If set, the folder is shown expanded (open) + /// when the archive contents are viewed in ZipIt. + /// + ShowExpanded = 0b0000_0000_0000_0001, + + /// + /// Reserved, zero + /// + Reserved1 = 0b0000_0000_0000_0010, + + /// + /// Reserved, zero + /// + Reserved2 = 0b0000_0000_0000_0100, + + /// + /// Reserved, zero + /// + Reserved3 = 0b0000_0000_0000_1000, + + /// + /// Reserved, zero + /// + Reserved4 = 0b0000_0000_0001_0000, + + /// + /// Reserved, zero + /// + Reserved5 = 0b0000_0000_0010_0000, + + /// + /// Reserved, zero + /// + Reserved6 = 0b0000_0000_0100_0000, + + /// + /// Reserved, zero + /// + Reserved7 = 0b0000_0000_1000_0000, + + /// + /// Reserved, zero + /// + Reserved8 = 0b0000_0001_0000_0000, + + /// + /// Reserved, zero + /// + Reserved9 = 0b0000_0010_0000_0000, + + /// + /// Reserved, zero + /// + Reserved10 = 0b0000_0100_0000_0000, + + /// + /// Reserved, zero + /// + Reserved11 = 0b0000_1000_0000_0000, + + /// + /// Reserved, zero + /// + Reserved12 = 0b0001_0000_0000_0000, + + /// + /// Reserved, zero + /// + Reserved13 = 0b0010_0000_0000_0000, + + /// + /// Reserved, zero + /// + Reserved14 = 0b0100_0000_0000_0000, + + /// + /// Reserved, zero + /// + Reserved15 = 0b1000_0000_0000_0000, + } + + public enum ZOSExtraFieldAttributeFieldCode : ushort + { + /// + /// File Type + /// + /// 2 bytes + FileType = 0x0001, + + /// + /// NonVSAM Record Format + /// + /// 1 byte + NonVSAMRecordFormat = 0x0002, + + /// + /// Reserved + /// + /// + Reserved03 = 0x0003, + + /// + /// NonVSAM Block Size + /// + /// 2 bytes Big Endian + NonVSAMBlockSize = 0x0004, + + /// + /// Primary Space Allocation + /// + /// 3 bytes Big Endian + PrimarySpaceAllocation = 0x0005, + + /// + /// Secondary Space Allocation + /// + /// 3 bytes Big Endian + SecondarySpaceAllocation = 0x0006, + + /// + /// Space Allocation Type1 byte flag + /// + /// 1 byte + SpaceAllocationType1ByteFlag = 0x0007, + + /// + /// Modification Date + /// + /// Retired with PKZIP 5.0 + + ModificationDate = 0x0008, + + /// + /// Expiration Date + /// + /// Retired with PKZIP 5.0 + + ExpirationDate = 0x0009, + + /// + /// PDS Directory Block Allocation + /// + /// 3 bytes Big Endian binary value + PDSDirectoryBlockAllocation = 0x000A, + + /// + /// NonVSAM Volume List + /// + /// variable + NonVSAMVolumeList = 0x000B, + + /// + /// UNIT Reference + /// + /// Retired with PKZIP 5.0 + + UNITReference = 0x000C, + + /// + /// DF/SMS Management Class + /// + /// 8 bytes EBCDIC Text Value + DFSMSManagementClass = 0x000D, + + /// + /// DF/SMS Storage Class + /// + /// 8 bytes EBCDIC Text Value + DFSMSStorageClass = 0x000E, + + /// + /// DF/SMS Data Class + /// + /// 8 bytes EBCDIC Text Value + DFSMSDataClass = 0x000F, + + /// + /// PDS/PDSE Member Info + /// + /// 30 bytes + PDSPDSEMemberInfo = 0x0010, + + /// + /// VSAM sub-filetype + /// + /// 2 bytes + VSAMSubFiletype = 0x0011, + + /// + /// VSAM LRECL + /// + /// 13 bytes EBCDIC "(num_avg num_max)" + VSAMLRECL = 0x0012, + + /// + /// VSAM Cluster Name + /// + /// Retired with PKZIP 5.0 + + VSAMClusterName = 0x0013, + + /// + /// VSAM KSDS Key Information + /// + /// 13 bytes EBCDIC "(num_length num_position)" + VSAMKSDSKeyInformation = 0x0014, + + /// + /// VSAM Average LRECL + /// + /// 5 bytes EBCDIC num_value padded with blanks + VSAMAverageLRECL = 0x0015, + + /// + /// VSAM Maximum LRECL + /// + /// 5 bytes EBCDIC num_value padded with blanks + VSAMMaximumLRECL = 0x0016, + + /// + /// VSAM KSDS Key Length + /// + /// 5 bytes EBCDIC num_value padded with blanks + VSAMKSDSKeyLength = 0x0017, + + /// + /// VSAM KSDS Key Position + /// + /// 5 bytes EBCDIC num_value padded with blanks + VSAMKSDSKeyPosition = 0x0018, + + /// + /// VSAM Data Name + /// + /// 1-44 bytes EBCDIC text string + VSAMDataName = 0x0019, + + /// + /// VSAM KSDS Index Name + /// + /// 1-44 bytes EBCDIC text string + VSAMKSDSIndexName = 0x001A, + + /// + /// VSAM Catalog Name + /// + /// 1-44 bytes EBCDIC text string + VSAMCatalogName = 0x001B, + + /// + /// VSAM Data Space Type + /// + /// 9 bytes EBCDIC text string + VSAMDataSpaceType = 0x001C, + + /// + /// VSAM Data Space Primary + /// + /// 9 bytes EBCDIC num_value left-justified + VSAMDataSpacePrimary = 0x001D, + + /// + /// VSAM Data Space Secondary + /// + /// 9 bytes EBCDIC num_value left-justified + VSAMDataSpaceSecondary = 0x001E, + + /// + /// VSAM Data Volume List + /// + /// variable EBCDIC text list of 6-character Volume IDs + VSAMDataVolumeList = 0x001F, + + /// + /// VSAM Data Buffer Space + /// + /// 8 bytes EBCDIC num_value left-justified + VSAMDataBufferSpace = 0x0020, + + /// + /// VSAM Data CISIZE + /// + /// 5 bytes EBCDIC num_value left-justified + VSAMDataCISIZE = 0x0021, + + /// + /// VSAM Erase Flag + /// + /// 1 byte flag + VSAMEraseFlag = 0x0022, + + /// + /// VSAM Free CI % + /// + /// 3 bytes EBCDIC num_value left-justified + VSAMFreeCIPercentage = 0x0023, + + /// + /// VSAM Free CA % + /// + /// 3 bytes EBCDIC num_value left-justified + VSAMFreeCAPercentage = 0x0024, + + /// + /// VSAM Index Volume List + /// + /// variable EBCDIC text list of 6-character Volume IDs + VSAMIndexVolumeList = 0x0025, + + /// + /// VSAM Ordered Flag + /// + /// 1 byte flag + VSAMOrderedFlag = 0x0026, + + /// + /// VSAM REUSE Flag + /// + /// 1 byte flag + VSAMREUSEFlag = 0x0027, + + /// + /// VSAM SPANNED Flag + /// + /// 1 byte flag + VSAMSPANNEDFlag = 0x0028, + + /// + /// VSAM Recovery Flag + /// + /// 1 byte flag + VSAMRecoveryFlag = 0x0029, + + /// + /// VSAM WRITECHK Flag + /// + /// 1 byte flag + VSAMWRITECHKFlag = 0x002A, + + /// + /// VSAM Cluster/Data SHROPTS + /// + /// 3 bytes EBCDIC "n,y" + CSAMClusterDataSHROPTS = 0x002B, + + /// + /// VSAM Index SHROPTS + /// + /// 3 bytes EBCDIC "n,y" + VSAMIndexSHROPTS = 0x002C, + + /// + /// VSAM Index Space Type + /// + /// 9 bytes EBCDIC text string + VSAMIndexSpaceType = 0x002D, + + /// + /// VSAM Index Space Primary + /// + /// 9 bytes EBCDIC num_value left-justified + VSAMIndexSpacePrimary = 0x002E, + + /// + /// VSAM Index Space Secondary + /// + /// 9 bytes EBCDIC num_value left-justified + VSAMIndexSpaceSecondary = 0x002F, + + /// + /// VSAM Index CISIZE + /// + /// v + VSAMIndexCISIZE = 0x0030, + + /// + /// VSAM Index IMBED + /// + /// 1 byte flag + VSAMIndexIMBED = 0x0031, + + /// + /// VSAM Index Ordered Flag + /// + /// 1 byte flag + VSAMIndexOrderedFlag = 0x0032, + + /// + /// VSAM REPLICATE Flag + /// + /// 1 byte flag + VSAMREPLICATEFlag = 0x0033, + + /// + /// VSAM Index REUSE Flag + /// + /// 1 byte flag + VSAMIndexREUSEFlag = 0x0034, + + /// + /// VSAM Index WRITECHK Flag + /// + /// 1 byte flag Retired with PKZIP 5.0 + + VSAMIndexWRITECHKFlag = 0x0035, + + /// + /// VSAM Owner + /// + /// 8 bytes EBCDIC text string + VSAMOwner = 0x0036, + + /// + /// VSAM Index Owner + /// + /// 8 bytes EBCDIC text string + VSAMIndexOwner = 0x0037, + + /// + /// Reserved + /// + Reserved38 = 0x0038, + + /// + /// Reserved + /// + Reserved39 = 0x0039, + + /// + /// Reserved + /// + Reserved3A = 0x003A, + + /// + /// Reserved + /// + Reserved3B = 0x003B, + + /// + /// Reserved + /// + Reserved3C = 0x003C, + + /// + /// Reserved + /// + Reserved3D = 0x003D, + + /// + /// Reserved + /// + Reserved3E = 0x003E, + + /// + /// Reserved + /// + ReservedeF = 0x003F, + + /// + /// Reserved + /// + Reserved40 = 0x0040, + + /// + /// Reserved + /// + Reserved41 = 0x0041, + + /// + /// Reserved + /// + Reserved42 = 0x0042, + + /// + /// Reserved + /// + Reserved43 = 0x0043, + + /// + /// Reserved + /// + Reserved44 = 0x0044, + + /// + /// Reserved + /// + Reserved45 = 0x0045, + + /// + /// Reserved + /// + Reserved46 = 0x0046, + + /// + /// Reserved + /// + Reserved47 = 0x0047, + + /// + /// Reserved + /// + Reserved48 = 0x0048, + + /// + /// Reserved + /// + Reserved49 = 0x0049, + + /// + /// Reserved + /// + Reserved4A = 0x004A, + + /// + /// Reserved + /// + Reserved4B = 0x004B, + + /// + /// Reserved + /// + Reserved4C = 0x004C, + + /// + /// Reserved + /// + Reserved4D = 0x004D, + + /// + /// Reserved + /// + Reserved4E = 0x004E, + + /// + /// Reserved + /// + Reserved4F = 0x004F, + + /// + /// Reserved + /// + Reserved50 = 0x0050, + + /// + /// Reserved + /// + Reserved51 = 0x0051, + + /// + /// Reserved + /// + Reserved52 = 0x0052, + + /// + /// Reserved + /// + Reserved53 = 0x0053, + + /// + /// Reserved + /// + Reserved54 = 0x0054, + + /// + /// Reserved + /// + Reserved55 = 0x0055, + + /// + /// Reserved + /// + Reserved56 = 0x0056, + + /// + /// Reserved + /// + Reserved57 = 0x0057, + + /// + /// PDS/PDSE Member TTR Info + /// + /// 6 bytes Big Endian + PDSPDSEMemberTTRInfo = 0x0058, + + /// + /// PDS 1st LMOD Text TTR + /// + /// 3 bytes Big Endian + PDSFirstLMODTextTTR = 0x0059, + + /// + /// PDS LMOD EP Rec # + /// + /// 4 bytes Big Endian + PDSLMODEPRecNum = 0x005A, + + /// + /// Reserved + /// + Reserved5B = 0x005B, + + /// + /// Max Length of records + /// + /// 2 bytes Big Endian + MaxLengthOfRecords = 0x005C, + + /// + /// PDSE Flag + /// + /// 1 byte flag + PDSEFlag = 0x005D, + + /// + /// Reserved + /// + Reserved5E = 0x005E, + + /// + /// Reserved + /// + Reserved5F = 0x005F, + + /// + /// Reserved + /// + Reserved60 = 0x0060, + + /// + /// Reserved + /// + Reserved61 = 0x0061, + + /// + /// Reserved + /// + Reserved62 = 0x0062, + + /// + /// Reserved + /// + Reserved63 = 0x0063, + + /// + /// Reserved + /// + Reserved64 = 0x0064, + + /// + /// Last Date Referenced + /// + /// 4 bytes Packed Hex "yyyymmdd" + LastDateReferenced = 0x0065, + + /// + /// Date Created + /// + /// 4 bytes Packed Hex "yyyymmdd" + DateCreated = 0x0066, + + /// + /// GZIP two words + /// + /// 8 bytes + GZIPTwoWords = 0x0068, + + /// + /// Extended NOTE Location + /// + /// 12 bytes Big Endian + ExtendedNOTELocation = 0x0071, + + /// + /// Archive device UNIT + /// + /// 6 bytes EBCDIC + ArchiveDeviceUNIT = 0x0072, + + /// + /// Archive 1st Volume + /// + /// 6 bytes EBCDIC + ArchiveFirstVolume = 0x0073, + + /// + /// Archive 1st VOL File Seq# + /// + /// 2 bytes Binary + ArchiveFirstVolFileSeqNum = 0x0074, + + /// + /// Native I/O Flags + /// + /// 2 bytes + NativeIOFlags = 0x0075, + + /// + /// Unix File Type + /// + /// 1 byte enumerated + UnixFileType = 0x0081, + + /// + /// Unix File Format + /// + /// 1 byte enumerated + UnixFileFormat = 0x0082, + + /// + /// Unix File Character Set Tag Info + /// + /// 4 bytes + UnixFileCharacterSetTagInfo = 0x0083, + + /// + /// ZIP Environmental Processing Info + /// + /// 4 bytes + ZIPEnvironmentalProcessingInfo = 0x0090, + + /// + /// EAV EATTR Flags + /// + /// 1 byte + EAVEATTRFlags = 0x0091, + + /// + /// DSNTYPE Flags + /// + /// 1 byte + DSNTYPEFlags = 0x0092, + + /// + /// Total Space Allocation (Cyls) + /// + /// 4 bytes Big Endian + TotalSpaceAllocationCyls = 0x0093, + + /// + /// NONVSAM DSORG + /// + /// 2 bytes + NONVSAMDSORG = 0x009D, + + /// + /// Program Virtual Object Info + /// + /// 3 bytes + ProgramVirtualObjectInfo = 0x009E, + + /// + /// Encapsulated file Info + /// + /// 9 bytes + EncapsulatedFileInfo = 0x009F, + + /// + /// Cluster Log + /// + /// 4 bytes Binary + ClusterLog = 0x00A2, + + /// + /// Cluster LSID Length + /// + /// 4 bytes Binary + ClusterLSIDLength = 0x00A3, + + /// + /// Cluster LSID + /// + /// 26 bytes EBCDIC + ClusterLSID = 0x00A4, + + /// + /// Unix File Creation Time + /// + /// 4 bytes + UnixFileCreationTime = 0x400C, + + /// + /// Unix File Access Time + /// + /// 4 bytes + UnixFileAccessTime = 0x400D, + + /// + /// Unix File Modification time + /// + /// 4 bytes + UnixFileModificationTime = 0x400E, + + /// + /// IBMCMPSC Compression Info + /// + /// variable + IBMCMPSCCompressionInfo = 0x4101, + + /// + /// IBMCMPSC Compression Size + /// + /// 8 bytes Big Endian + IBMCMPSCCompressionSize = 0x4102, + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ExtendedTimestampExtraField.cs b/SabreTools.Serialization/Models/PKZIP/ExtendedTimestampExtraField.cs new file mode 100644 index 00000000..c9f16d21 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ExtendedTimestampExtraField.cs @@ -0,0 +1,33 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The unix modified time, last access time, and creation time, if set + /// + /// Header ID = 0x5455 + /// + public class ExtendedTimestampExtraField : ExtensibleDataField + { + /// + /// Indicates what tiemstamps are included + /// + public RecordedTimeFlag Flags { get; set; } + + /// + /// Last modified time + /// + /// Only available when is set + public uint? LastModified { get; set; } + + /// + /// Last accessed time + /// + /// Only available when is set + public uint? LastAccessed { get; set; } + + /// + /// Created on time + /// + /// Only available when is set + public uint? CreatedOn { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ExtensibleDataField.cs b/SabreTools.Serialization/Models/PKZIP/ExtensibleDataField.cs new file mode 100644 index 00000000..983c4dc1 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ExtensibleDataField.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// In order to allow different programs and different types + /// of information to be stored in the 'extra' field in .ZIP + /// files, the following structure MUST be used for all + /// programs storing data in this field + /// + /// + public abstract class ExtensibleDataField + { + /// + /// Header ID + /// + public HeaderID HeaderID { get; set; } + + /// + /// Data Size + /// + public ushort DataSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/FWKCSMD5ExtraField.cs b/SabreTools.Serialization/Models/PKZIP/FWKCSMD5ExtraField.cs new file mode 100644 index 00000000..f9bf1b6f --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/FWKCSMD5ExtraField.cs @@ -0,0 +1,39 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The FWKCS Contents_Signature System, used in + /// automatically identifying files independent of file name, + /// optionally adds and uses an extra field to support the + /// rapid creation of an enhanced contents_signature. + /// + /// When FWKCS revises a .ZIP file central directory to add + /// this extra field for a file, it also replaces the + /// central directory entry for that file's uncompressed + /// file length with a measured value. + /// + /// FWKCS provides an option to strip this extra field, if + /// present, from a .ZIP file central directory. In adding + /// this extra field, FWKCS preserves .ZIP file Authenticity + /// Verification; if stripping this extra field, FWKCS + /// preserves all versions of AV through PKZIP version 2.04g. + /// + /// FWKCS, and FWKCS Contents_Signature System, are + /// trademarks of Frederick W. Kantor. + /// + /// Header ID = 0x4b46 + /// + public class FWKCSMD5ExtraField : ExtensibleDataField + { + /// + /// "MD5" + /// + /// 3 bytes + public byte[]? Preface { get; set; } + + /// + /// Uncompressed file's MD5 hash, low byte first + /// + /// 16 bytes + public byte[]? MD5 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodeCommentExtraField.cs b/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodeCommentExtraField.cs new file mode 100644 index 00000000..26944086 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodeCommentExtraField.cs @@ -0,0 +1,54 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Stores the UTF-8 version of the file comment as stored in the + /// central directory header. (Last Revision 20070912) + /// + /// Currently Version is set to the number 1. If there is a need + /// to change this field, the version will be incremented. Changes + /// MAY NOT be backward compatible so this extra field SHOULD NOT be + /// used if the version is not recognized. + /// + /// The ComCRC32 is the standard zip CRC32 checksum of the File Comment + /// field in the central directory header. This is used to verify that + /// the comment field has not changed since the Unicode Comment extra field + /// was created. This can happen if a utility changes the File Comment + /// field but does not update the UTF-8 Comment extra field. If the CRC + /// check fails, this Unicode Comment extra field SHOULD be ignored and + /// the File Comment field in the header SHOULD be used instead. + /// + /// The UnicodeCom field is the UTF-8 version of the File Comment field + /// in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte + /// order mark (BOM) is used. The length of this field is determined by + /// subtracting the size of the previous fields from TSize. If both the + /// File Name and Comment fields are UTF-8, the new General Purpose Bit + /// Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate + /// both the header File Name and Comment fields are UTF-8 and, in this + /// case, the Unicode Path and Unicode Comment extra fields are not + /// needed and SHOULD NOT be created. Note that, for backward + /// compatibility, bit 11 SHOULD only be used if the native character set + /// of the paths and comments being zipped up are already in UTF-8. It is + /// expected that the same file comment storage method, either general + /// purpose bit 11 or extra fields, be used in both the Local and Central + /// Directory Header for a file. + /// + /// Header ID = 0x6375 + /// + public class InfoZIPUnicodeCommentExtraField : ExtensibleDataField + { + /// + /// Version of this extra field, currently 1 + /// + public byte Version { get; set; } + + /// + /// Comment Field CRC32 Checksum + /// + public uint ComCRC32 { get; set; } + + /// + /// UTF-8 version of the entry comment + /// + public string? UnicodeCom { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodePathExtraField.cs b/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodePathExtraField.cs new file mode 100644 index 00000000..f357e57d --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/InfoZIPUnicodePathExtraField.cs @@ -0,0 +1,54 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Stores the UTF-8 version of the file name field as stored in the + /// local header and central directory header. (Last Revision 20070912) + /// + /// Currently Version is set to the number 1. If there is a need + /// to change this field, the version will be incremented. Changes + /// MAY NOT be backward compatible so this extra field SHOULD NOT be + /// used if the version is not recognized. + /// + /// The NameCRC32 is the standard zip CRC32 checksum of the File Name + /// field in the header. This is used to verify that the header + /// File Name field has not changed since the Unicode Path extra field + /// was created. This can happen if a utility renames the File Name but + /// does not update the UTF-8 path extra field. If the CRC check fails, + /// this UTF-8 Path Extra Field SHOULD be ignored and the File Name field + /// in the header SHOULD be used instead. + /// + /// The UnicodeName is the UTF-8 version of the contents of the File Name + /// field in the header. As UnicodeName is defined to be UTF-8, no UTF-8 + /// byte order mark (BOM) is used. The length of this field is determined + /// by subtracting the size of the previous fields from TSize. If both + /// the File Name and Comment fields are UTF-8, the new General Purpose + /// Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to + /// indicate that both the header File Name and Comment fields are UTF-8 + /// and, in this case, the Unicode Path and Unicode Comment extra fields + /// are not needed and SHOULD NOT be created. Note that, for backward + /// compatibility, bit 11 SHOULD only be used if the native character set + /// of the paths and comments being zipped up are already in UTF-8. It is + /// expected that the same file name storage method, either general + /// purpose bit 11 or extra fields, be used in both the Local and Central + /// Directory Header for a file. + /// + /// Header ID = 0x7075 + /// + public class InfoZIPUnicodePathExtraField : ExtensibleDataField + { + /// + /// Version of this extra field, currently 1 + /// + public byte Version { get; set; } + + /// + /// File Name Field CRC32 Checksum + /// + public uint NameCRC32 { get; set; } + + /// + /// UTF-8 version of the entry File Name + /// + public string? UnicodeName { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/KeyProviderRecordExtraField.cs b/SabreTools.Serialization/Models/PKZIP/KeyProviderRecordExtraField.cs new file mode 100644 index 00000000..b7e6bd5d --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/KeyProviderRecordExtraField.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the Key Provider "extra" block. + /// TData is a variable length, variable content field. It holds + /// information about encryptions and/or encryption key sources. + /// Contact PKWARE for information on current TData structures. + /// Information in this "extra" block may aternatively be placed + /// within comment fields. Refer to the section in this document + /// entitled "Incorporating PKWARE Proprietary Technology into Your + /// Product" for more information. + /// + /// Header ID = 0x0022 + /// + public class KeyProviderRecordExtraField : ExtensibleDataField + { + /// + /// Data about the key + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/LocalFile.cs b/SabreTools.Serialization/Models/PKZIP/LocalFile.cs new file mode 100644 index 00000000..5eed24c0 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/LocalFile.cs @@ -0,0 +1,40 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// PKZIP local file + /// + /// + /// + public class LocalFile + { + /// + /// Local file header + /// + public LocalFileHeader? LocalFileHeader { get; set; } + + /// + /// Encryption header + /// + /// TODO: Determine the model for the encryption headers + public byte[]? EncryptionHeaders { get; set; } + + /// + /// File data, appears after the encryption header + /// if it exists or after the local file header otherwise + /// + public byte[]? FileData { get; set; } + + /// + /// Data descriptors, appears after the file data + /// + /// Cannot exist if is populated + public DataDescriptor? DataDescriptor { get; set; } + + /// + /// ZIP64 Data descriptors, appears after the file data + /// + /// Cannot exist if is populated + public DataDescriptor64? ZIP64DataDescriptor { get; set; } + + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/LocalFileHeader.cs b/SabreTools.Serialization/Models/PKZIP/LocalFileHeader.cs new file mode 100644 index 00000000..92c764ad --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/LocalFileHeader.cs @@ -0,0 +1,77 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// PKZIP local file header + /// + /// + /// + public class LocalFileHeader + { + /// + /// Signature (0x04034B50) + /// + public uint Signature { get; set; } + + /// + /// Version needed to extract + /// decimal value/10 = major version # + /// decimal value%10 = minor version # + /// + public ushort Version { get; set; } + + /// + /// General purpose bit flag + /// + public GeneralPurposeBitFlags Flags { get; set; } + + /// + /// Compression method + /// + public CompressionMethod CompressionMethod { get; set; } + + /// + /// Last modified file time + /// + public ushort LastModifedFileTime { get; set; } + + /// + /// Last modified file date + /// + public ushort LastModifiedFileDate { get; set; } + + /// + /// CRC-32 + /// + public uint CRC32 { get; set; } + + /// + /// Compressed size + /// + public uint CompressedSize { get; set; } + + /// + /// Uncompressed size + /// + public uint UncompressedSize { get; set; } + + /// + /// File name length + /// + public ushort FileNameLength { get; set; } + + /// + /// Extra field length + /// + public ushort ExtraFieldLength { get; set; } + + /// + /// File name (variable size) + /// + public string? FileName { get; set; } + + /// + /// Extra fields (variable size) + /// + public ExtensibleDataField[]? ExtraFields { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/MVSExtraField.cs b/SabreTools.Serialization/Models/PKZIP/MVSExtraField.cs new file mode 100644 index 00000000..184d12c9 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/MVSExtraField.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the MVS "extra" block. + /// + /// Header ID = 0x0065 + /// + public class MVSExtraField : ExtensibleDataField + { + /// + /// EBCDIC "Z390" 0xE9F3F9F0 + /// or "T4MV" for TargetFour + /// + public uint ID { get; set; } + + /// + /// Attribute data (see APPENDIX B) + /// + public byte[]? Var { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/MicrosoftOpenPackagingGrowthHint.cs b/SabreTools.Serialization/Models/PKZIP/MicrosoftOpenPackagingGrowthHint.cs new file mode 100644 index 00000000..289800cd --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/MicrosoftOpenPackagingGrowthHint.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// Header ID = 0xa220 + /// + public class MicrosoftOpenPackagingGrowthHint : ExtensibleDataField + { + /// + /// Verification signature (A028) + /// + public ushort Sig { get; set; } + + /// + /// Initial padding value + /// + public ushort PadVal { get; set; } + + /// + /// Filled with NULL characters + /// + public byte[]? Padding { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/NTFSExtraField.cs b/SabreTools.Serialization/Models/PKZIP/NTFSExtraField.cs new file mode 100644 index 00000000..4f8a636c --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/NTFSExtraField.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the NTFS attributes + /// "extra" block. (Note: At this time the Mtime, Atime + /// and Ctime values MAY be used on any WIN32 system.) + /// + /// Header ID = 0x000A + /// + public class NTFSExtraField : ExtensibleDataField + { + /// + /// Reserved for future use + /// + public uint Reserved { get; set; } + + /// + /// NTFS attribute tags + /// + public TagSizeVar[]? TagSizeVars { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/OS2ExtraField.cs b/SabreTools.Serialization/Models/PKZIP/OS2ExtraField.cs new file mode 100644 index 00000000..16413d38 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/OS2ExtraField.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the OS/2 attributes "extra" + /// block. (Last Revision 09/05/95) + /// + /// The OS/2 extended attribute structure (FEA2LIST) is + /// compressed and then stored in its entirety within this + /// structure. There will only ever be one "block" of data in + /// VarFields[]. + /// + /// Header ID = 0x0009 + /// + public class OS2ExtraField : ExtensibleDataField + { + /// + /// Uncompressed Block Size + /// + public uint UncompressedBlockSize { get; set; } + + /// + /// Compression type + /// + public ushort CompressionType { get; set; } + + /// + /// CRC value for uncompress block + /// + public uint CRC32 { get; set; } + + /// + /// Compressed block + /// + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/OS400ExtraField.cs b/SabreTools.Serialization/Models/PKZIP/OS400ExtraField.cs new file mode 100644 index 00000000..ae38071e --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/OS400ExtraField.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the OS/400 "extra" block. + /// + /// Header ID = 0x0065 + /// + public class OS400ExtraField : ExtensibleDataField + { + /// + /// EBCDIC "Z390" 0xE9F3F9F0 + /// or "T4MV" for TargetFour + /// + public uint ID { get; set; } + + /// + /// Attribute data (see APPENDIX A) + /// + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/OpenVMSExtraField.cs b/SabreTools.Serialization/Models/PKZIP/OpenVMSExtraField.cs new file mode 100644 index 00000000..69044b77 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/OpenVMSExtraField.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the OpenVMS attributes + /// "extra" block. + /// + /// OpenVMS Extra Field Rules: + /// + /// - There will be one or more attributes present, which + /// will each be preceded by the above TagX & SizeX values. + /// These values are identical to the ATR$C_XXXX and ATR$S_XXXX + /// constants which are defined in ATR.H under OpenVMS C. Neither + /// of these values will ever be zero. + /// + /// - No word alignment or padding is performed. + /// + /// - A well-behaved PKZIP/OpenVMS program SHOULD NOT produce + /// more than one sub-block with the same TagX value. Also, there MUST + /// NOT be more than one "extra" block of type 0x000c in a particular + /// directory record. + /// + /// Header ID = 0x000C + /// + public class OpenVMSExtraField : ExtensibleDataField + { + /// + /// 32-bit CRC for remainder of the block + /// + public uint CRC { get; set; } + + /// + /// OpenVMS attribute tags + /// + public TagSizeVar[]? TagSizeVars { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/PKCS7EncryptionRecipientCertificateList.cs b/SabreTools.Serialization/Models/PKZIP/PKCS7EncryptionRecipientCertificateList.cs new file mode 100644 index 00000000..032ef281 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/PKCS7EncryptionRecipientCertificateList.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This field MAY contain information about each of the certificates + /// used in encryption processing and it can be used to identify who is + /// allowed to decrypt encrypted files. This field SHOULD only appear + /// in the archive extra data record. This field is not required and + /// serves only to aid archive modifications by preserving public + /// encryption key data. Individual security requirements may dictate + /// that this data be omitted to deter information exposure. + /// + /// See the section describing the Strong Encryption Specification + /// for details. Refer to the section in this document entitled + /// "Incorporating PKWARE Proprietary Technology into Your Product" + /// for more information. + /// + /// Header ID = 0x0019 + /// + public class PKCS7EncryptionRecipientCertificateList : ExtensibleDataField + { + /// + /// Format version number - MUST be 0x0001 at this time + /// + public ushort Version { get; set; } + + /// + /// PKCS#7 data blob + /// + public byte[]? CStore { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/PKCS7Store.cs b/SabreTools.Serialization/Models/PKZIP/PKCS7Store.cs new file mode 100644 index 00000000..3adec652 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/PKCS7Store.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This field MUST contain information about each of the certificates + /// files MAY be signed with. When the Central Directory Encryption + /// feature is enabled for a ZIP file, this record will appear in + /// the Archive Extra Data Record, otherwise it will appear in the + /// first central directory record and will be ignored in any + /// other record. + /// + /// Header ID = 0x0014 + /// + public class PKCS7Store : ExtensibleDataField + { + /// + /// Data about the store + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/PatchDescriptorExtraField.cs b/SabreTools.Serialization/Models/PKZIP/PatchDescriptorExtraField.cs new file mode 100644 index 00000000..d25562d8 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/PatchDescriptorExtraField.cs @@ -0,0 +1,50 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the Patch Descriptor + /// "extra" block. + /// + /// Patch support is provided by PKPatchMaker(tm) technology + /// and is covered under U.S. Patents and Patents Pending. The use or + /// implementation in a product of certain technological aspects set + /// forth in the current APPNOTE, including those with regard to + /// strong encryption or patching requires a license from PKWARE. + /// Refer to the section in this document entitled "Incorporating + /// PKWARE Proprietary Technology into Your Product" for more + /// information. + /// + /// Header ID = 0x000F + /// + public class PatchDescriptorExtraField : ExtensibleDataField + { + /// + /// Version of the descriptor + /// + public ushort Version { get; set; } + + /// + /// Actions and reactions + /// + public ActionsReactions Flags { get; set; } + + /// + /// Size of the file about to be patched + /// + public uint OldSize { get; set; } + + /// + /// 32-bit CRC of the file to be patched + /// + public uint OldCRC { get; set; } + + /// + /// Size of the resulting file + /// + public uint NewSize { get; set; } + + /// + /// 32-bit CRC of the resulting file + /// + public uint NewCRC { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/PolicyDecryptionKeyRecordExtraField.cs b/SabreTools.Serialization/Models/PKZIP/PolicyDecryptionKeyRecordExtraField.cs new file mode 100644 index 00000000..148e4012 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/PolicyDecryptionKeyRecordExtraField.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the Policy Decryption Key "extra" block. + /// TData is a variable length, variable content field. It holds + /// information about encryptions and/or encryption key sources. + /// Contact PKWARE for information on current TData structures. + /// Information in this "extra" block may aternatively be placed + /// within comment fields. Refer to the section in this document + /// entitled "Incorporating PKWARE Proprietary Technology into Your + /// Product" for more information. + /// + /// Header ID = 0x0021 + /// + public class PolicyDecryptionKeyRecordExtraField : ExtensibleDataField + { + /// + /// Data about the key + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/PolicyKeyDataRecordRecordExtraField.cs b/SabreTools.Serialization/Models/PKZIP/PolicyKeyDataRecordRecordExtraField.cs new file mode 100644 index 00000000..ed9c2dee --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/PolicyKeyDataRecordRecordExtraField.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the Policy Key Data "extra" block. + /// TData is a variable length, variable content field. It holds + /// information about encryptions and/or encryption key sources. + /// Contact PKWARE for information on current TData structures. + /// Information in this "extra" block may aternatively be placed + /// within comment fields. Refer to the section in this document + /// entitled "Incorporating PKWARE Proprietary Technology into Your + /// Product" for more information. + /// + /// Header ID = 0x0023 + /// + public class PolicyKeyDataRecordRecordExtraField : ExtensibleDataField + { + /// + /// Data about the key + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/RecordManagementControls.cs b/SabreTools.Serialization/Models/PKZIP/RecordManagementControls.cs new file mode 100644 index 00000000..28f980bd --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/RecordManagementControls.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// Header ID = 0x0018 + /// + public class RecordManagementControls : ExtensibleDataField + { + /// + /// Record management control attribute tags + /// + public TagSizeVar[]? TagSizeVars { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/SpecialPurposeDataHeader.cs b/SabreTools.Serialization/Models/PKZIP/SpecialPurposeDataHeader.cs new file mode 100644 index 00000000..f3b1825d --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/SpecialPurposeDataHeader.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// Special purpose data for ZIP64 extensible data field + /// + /// + public class SpecialPurposeDataHeader + { + /// + /// Header ID (data type) + /// + public HeaderID HeaderID { get; set; } + + /// + /// Data size + /// + public uint DataSize { get; set; } + + /// + /// Data (variable size) + /// + /// TODO: Implement models for all extra field types - 4.5.3 + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/StrongEncryptionHeader.cs b/SabreTools.Serialization/Models/PKZIP/StrongEncryptionHeader.cs new file mode 100644 index 00000000..267bf153 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/StrongEncryptionHeader.cs @@ -0,0 +1,44 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// See the section describing the Strong Encryption Specification + /// for details. Refer to the section in this document entitled + /// "Incorporating PKWARE Proprietary Technology into Your Product" + /// for more information. + /// + /// Header ID = 0x0017 + /// + public class StrongEncryptionHeader : ExtensibleDataField + { + /// + /// Format definition for this record + /// + public ushort Format { get; set; } + + /// + /// Encryption algorithm identifier + /// + public ushort AlgID { get; set; } + + /// + /// Bit length of encryption key + /// + public ushort Bitlen { get; set; } + + /// + /// Processing flags + /// + public ushort Flags { get; set; } + + /// + /// Certificate decryption extra field data + /// + /// + /// Refer to the explanation for CertData + /// in the section describing the + /// Certificate Processing Method under + /// the Strong Encryption Specification + /// + public byte[]? CertData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/TagSizeVar.cs b/SabreTools.Serialization/Models/PKZIP/TagSizeVar.cs new file mode 100644 index 00000000..306a2c52 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/TagSizeVar.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This represents a common tag/size/data combination + /// structure that is used by multiple extra field types. + /// + public class TagSizeVar + { + /// + /// Attribute tag + /// + public ushort Tag { get; set; } + + /// + /// Attribute size + /// + public ushort Size { get; set; } + + /// + /// Variable-length data + /// + public byte[]? Var { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/UnixExtraField.cs b/SabreTools.Serialization/Models/PKZIP/UnixExtraField.cs new file mode 100644 index 00000000..1fd04571 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/UnixExtraField.cs @@ -0,0 +1,49 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the UNIX "extra" block. + /// + /// The variable length data field will contain file type + /// specific data. Currently the only values allowed are + /// the original "linked to" file names for hard or symbolic + /// links, and the major and minor device node numbers for + /// character and block device nodes. Since device nodes + /// cannot be either symbolic or hard links, only one set of + /// variable length data is stored. Link files will have the + /// name of the original file stored. This name is NOT NULL + /// terminated. Its size can be determined by checking TSize - + /// 12. Device entries will have eight bytes stored as two 4 + /// byte entries (in little endian format). The first entry + /// will be the major device number, and the second the minor + /// device number. + /// + /// Header ID = 0x000D + /// + public class UnixExtraField : ExtensibleDataField + { + /// + /// File last access time + /// + public uint FileLastAccessTime { get; set; } + + /// + /// File last modification time + /// + public uint FileLastModificationTime { get; set; } + + /// + /// File user ID + /// + public ushort FileUserID { get; set; } + + /// + /// File group ID + /// + public ushort FileGroupID { get; set; } + + /// + /// Variable length data field + /// + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/UnknownExtraField.cs b/SabreTools.Serialization/Models/PKZIP/UnknownExtraField.cs new file mode 100644 index 00000000..062c0e89 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/UnknownExtraField.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This represents any unknown extras fields that are either + /// unmapped or undiscovered. All unknown header IDs map to + /// this data type. + /// + public class UnknownExtraField : ExtensibleDataField + { + /// + /// + /// + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/X509CentralDirectory.cs b/SabreTools.Serialization/Models/PKZIP/X509CentralDirectory.cs new file mode 100644 index 00000000..5cd82c0d --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/X509CentralDirectory.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This field contains the information about which certificate in + /// the PKCS#7 store was used to sign the central directory structure. + /// When the Central Directory Encryption feature is enabled for a + /// ZIP file, this record will appear in the Archive Extra Data Record, + /// otherwise it will appear in the first central directory record. + /// + /// Header ID = 0x0016 + /// + public class X509CentralDirectory : ExtensibleDataField + { + /// + /// Data + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/X509IndividualFile.cs b/SabreTools.Serialization/Models/PKZIP/X509IndividualFile.cs new file mode 100644 index 00000000..0472ee5b --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/X509IndividualFile.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// This field contains the information about which certificate in + /// the PKCS#7 store was used to sign a particular file. It also + /// contains the signature data. This field can appear multiple + /// times, but can only appear once per certificate. + /// + /// Header ID = 0x0015 + /// + public class X509IndividualFile : ExtensibleDataField + { + /// + /// Signature Data + /// + public byte[]? TData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ZOSExtraFieldAttribute.cs b/SabreTools.Serialization/Models/PKZIP/ZOSExtraFieldAttribute.cs new file mode 100644 index 00000000..a5831982 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ZOSExtraFieldAttribute.cs @@ -0,0 +1,26 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// z/OS Extra Field (0x0065) Attribute [APPENDIX B] + /// + /// + public class ZOSExtraFieldAttribute : ExtensibleDataField + { + /// + /// Field length including length + /// + /// Big-endian + public ushort FieldLength { get; set; } + + /// + /// Field code + /// + public ZOSExtraFieldAttributeFieldCode FieldCode { get; set; } + + /// + /// Data + /// + /// Variable byte length based on field code + public byte[]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/Zip64ExtendedInformationExtraField.cs b/SabreTools.Serialization/Models/PKZIP/Zip64ExtendedInformationExtraField.cs new file mode 100644 index 00000000..8aec1c68 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/Zip64ExtendedInformationExtraField.cs @@ -0,0 +1,48 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the zip64 extended + /// information "extra" block. If one of the size or + /// offset fields in the Local or Central directory + /// record is too small to hold the required data, + /// a Zip64 extended information record is created. + /// The order of the fields in the zip64 extended + /// information record is fixed, but the fields MUST + /// only appear if the corresponding Local or Central + /// directory record field is set to 0xFFFF or 0xFFFFFFFF. + /// + /// This entry in the Local header MUST include BOTH original + /// and compressed file size fields. If encrypting the + /// central directory and bit 13 of the general purpose bit + /// flag is set indicating masking, the value stored in the + /// Local Header for the original file size will be zero. + /// + /// Header ID = 0x0001 + /// + public class Zip64ExtendedInformationExtraField : ExtensibleDataField + { + /// + /// Original uncompressed file size + /// + /// Only exists if parent entry corresponding value is max + public ulong? OriginalSize { get; set; } + + /// + /// Size of compressed data + /// + /// Only exists if parent entry corresponding value is max + public ulong? CompressedSize { get; set; } + + /// + /// Offset of local header record + /// + /// Only exists if parent entry corresponding value is max + public ulong? RelativeHeaderOffset { get; set; } + + /// + /// Number of the disk on which this file starts + /// + /// Only exists if parent entry corresponding value is max + public uint? DiskStartNumber { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshExtraField.cs b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshExtraField.cs new file mode 100644 index 00000000..6363ae44 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshExtraField.cs @@ -0,0 +1,41 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of the ZipIt extra block + /// for Macintosh. The local-header and central-header versions + /// are identical. This block MUST be present if the file is + /// stored MacBinary-encoded and it SHOULD NOT be used if the file + /// is not stored MacBinary-encoded. + /// + /// Header ID = 0x2605 + /// + public class ZipItMacintoshExtraField : ExtensibleDataField + { + /// + /// "ZPIT" - extra-field signature + /// + public uint ExtraFieldSignature { get; set; } + + /// + /// Length of FileName + /// + public byte FnLen { get; set; } + + /// + /// Full Macintosh filename + /// + public string? FileName { get; set; } + + /// + /// Four-byte Mac file type string + /// + /// 4 bytes + public byte[]? FileType { get; set; } + + /// + /// Four-byte Mac creator string + /// + /// 4 bytes + public byte[]? Creator { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortDirectoryExtraField.cs b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortDirectoryExtraField.cs new file mode 100644 index 00000000..0ed214ca --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortDirectoryExtraField.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of a shortened variant of the + /// ZipIt extra block for Macintosh used only for directory + /// entries. This variant is used by ZipIt 1.3.5 and newer to + /// save some optional Mac-specific information about directories. + /// The local-header and central-header versions are identical. + /// + /// Header ID = 0x2805 + /// + public class ZipItMacintoshShortDirectoryExtraField : ExtensibleDataField + { + /// + /// "ZPIT" - extra-field signature + /// + public uint ExtraFieldSignature { get; set; } + + /// + /// attributes from DInfo.frFlags, MAY be omitted + /// + public ushort? FrFlags { get; set; } + + /// + /// ZipIt view flag, MAY be omitted + /// + public ZipItInternalSettings? View { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortFileExtraField.cs b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortFileExtraField.cs new file mode 100644 index 00000000..7ece3059 --- /dev/null +++ b/SabreTools.Serialization/Models/PKZIP/ZipItMacintoshShortFileExtraField.cs @@ -0,0 +1,41 @@ +namespace SabreTools.Serialization.Models.PKZIP +{ + /// + /// The following is the layout of a shortened variant of the + /// ZipIt extra block for Macintosh (without "full name" entry). + /// This variant is used by ZipIt 1.3.5 and newer for entries of + /// files (not directories) that do not have a MacBinary encoded + /// file. The local-header and central-header versions are identical. + /// + /// Header ID = 0x2705 + /// + public class ZipItMacintoshShortFileExtraField : ExtensibleDataField + { + /// + /// "ZPIT" - extra-field signature + /// + public uint ExtraFieldSignature { get; set; } + + /// + /// Four-byte Mac file type string + /// + /// 4 bytes + public byte[]? FileType { get; set; } + + /// + /// Four-byte Mac creator string + /// + /// 4 bytes + public byte[]? Creator { get; set; } + + /// + /// Attributes from FInfo.frFlags, MAY be omitted + /// + public ushort? FdFlags { get; set; } + + /// + /// Reserved, MAY be omitted + /// + public ushort? Reserved { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/Quantum/Archive.cs b/SabreTools.Serialization/Models/Quantum/Archive.cs new file mode 100644 index 00000000..d77aa561 --- /dev/null +++ b/SabreTools.Serialization/Models/Quantum/Archive.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.Quantum +{ + /// + /// Quantum archive file structure + /// + /// + public class Archive + { + /// + /// Quantum header + /// + public Header? Header { get; set; } + + /// + /// This is immediately followed by the list of files + /// + public FileDescriptor[]? FileList { get; set; } + + /// + /// Immediately following the list of files is the compressed data + /// + public long CompressedDataOffset { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Quantum/Constants.cs b/SabreTools.Serialization/Models/Quantum/Constants.cs new file mode 100644 index 00000000..f49058a8 --- /dev/null +++ b/SabreTools.Serialization/Models/Quantum/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.Quantum +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x44, 0x53]; + + public const string SignatureString = "DS"; + + public const ushort SignatureUInt16 = 0x5344; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Quantum/FileDescriptor.cs b/SabreTools.Serialization/Models/Quantum/FileDescriptor.cs new file mode 100644 index 00000000..00c3f524 --- /dev/null +++ b/SabreTools.Serialization/Models/Quantum/FileDescriptor.cs @@ -0,0 +1,50 @@ +namespace SabreTools.Serialization.Models.Quantum +{ + /// + /// Quantum archive file descriptor + /// + /// + public class FileDescriptor + { + /// + /// Length of file name + /// + public int FileNameSize { get; set; } + + /// + /// File name, variable length string, not zero-terminated + /// + public string? FileName { get; set; } + + /// + /// Length of comment field + /// + public int CommentFieldSize { get; set; } + + /// + /// Comment field, variable length string, not zero-terminated + /// + public string? CommentField { get; set; } + + /// + /// Fully expanded file size in bytes + /// + public uint ExpandedFileSize { get; set; } + + /// + /// File time (DOS format) + /// + public ushort FileTime { get; set; } + + /// + /// File date (DOS format) + /// + public ushort FileDate { get; set; } + + /// + /// Unknown data, Checksum? + /// + /// Minor version 22 + public ushort? Unknown { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Quantum/Header.cs b/SabreTools.Serialization/Models/Quantum/Header.cs new file mode 100644 index 00000000..43d8cbf0 --- /dev/null +++ b/SabreTools.Serialization/Models/Quantum/Header.cs @@ -0,0 +1,43 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.Quantum +{ + /// + /// Quantum archive file header + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public class Header + { + /// + /// Quantum signature: 0x44 0x53 + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] + public string? Signature; + + /// + /// Quantum major version number + /// + public byte MajorVersion; + + /// + /// Quantum minor version number + /// + public byte MinorVersion; + + /// + /// Number of files within this archive + /// + public ushort FileCount; + + /// + /// Table size required for decompression + /// + public byte TableSize; + + /// + /// Compression flags + /// + public byte CompressionFlags; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/RAR/Archive.cs b/SabreTools.Serialization/Models/RAR/Archive.cs new file mode 100644 index 00000000..7f335eda --- /dev/null +++ b/SabreTools.Serialization/Models/RAR/Archive.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.RAR +{ + /// + /// This is a placeholder model for future work + /// + public class Archive + { + + } +} diff --git a/SabreTools.Serialization/Models/RAR/Constants.cs b/SabreTools.Serialization/Models/RAR/Constants.cs new file mode 100644 index 00000000..06df448b --- /dev/null +++ b/SabreTools.Serialization/Models/RAR/Constants.cs @@ -0,0 +1,9 @@ +namespace SabreTools.Serialization.Models.RAR +{ + public static class Constants + { + public static readonly byte[] OldSignatureBytes = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00]; + + public static readonly byte[] NewSignatureBytes = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SGA/Archive.cs b/SabreTools.Serialization/Models/SGA/Archive.cs new file mode 100644 index 00000000..920cf06c --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Archive.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + /// SGA game archive + /// + /// + public sealed class Archive + { + /// + ///Header data + /// + public Header? Header { get; set; } + + /// + /// Directory data + /// + public Directory? Directory { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Constants.cs b/SabreTools.Serialization/Models/SGA/Constants.cs new file mode 100644 index 00000000..b9d488fb --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Constants.cs @@ -0,0 +1,16 @@ +namespace SabreTools.Serialization.Models.SGA +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45]; + + public const string SignatureString = "_ARCHIVE"; + + public const ulong SignatureUInt64 = 0x455649484352415f; + + /// + /// Length of a SGA checksum in bytes + /// + public const int HL_SGA_CHECKSUM_LENGTH = 0x00008000; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SGA/Directory.cs b/SabreTools.Serialization/Models/SGA/Directory.cs new file mode 100644 index 00000000..458421bd --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Directory.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class Directory + { + /// + /// Source SGA file + /// + public Archive? File { get; set; } + } + + /// + /// Specialization File7 and up where the CRC moved to the header and the CRC is of the compressed data and there are stronger hashes. + /// + /// + public class Directory : Directory + where THeader : Header + where TDirectoryHeader : DirectoryHeader + where TSection : Section + where TFolder : Folder + where TFile : File + { + /// + /// Directory header data + /// + public TDirectoryHeader? DirectoryHeader { get; set; } + + /// + /// Sections data + /// + public TSection[]? Sections { get; set; } + + /// + /// Folders data + /// + public TFolder[]? Folders { get; set; } + + /// + /// Files data + /// + public TFile[]? Files { get; set; } + + /// + /// String table data + /// + public Dictionary? StringTable { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Directory4.cs b/SabreTools.Serialization/Models/SGA/Directory4.cs new file mode 100644 index 00000000..f6efec34 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Directory4.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Directory4 : Directory { } +} diff --git a/SabreTools.Serialization/Models/SGA/Directory5.cs b/SabreTools.Serialization/Models/SGA/Directory5.cs new file mode 100644 index 00000000..8e7253d5 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Directory5.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Directory5 : Directory { } +} diff --git a/SabreTools.Serialization/Models/SGA/Directory6.cs b/SabreTools.Serialization/Models/SGA/Directory6.cs new file mode 100644 index 00000000..eea4762e --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Directory6.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Directory6 : Directory { } +} diff --git a/SabreTools.Serialization/Models/SGA/Directory7.cs b/SabreTools.Serialization/Models/SGA/Directory7.cs new file mode 100644 index 00000000..6b6af6a6 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Directory7.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Directory7 : Directory { } +} diff --git a/SabreTools.Serialization/Models/SGA/DirectoryHeader.cs b/SabreTools.Serialization/Models/SGA/DirectoryHeader.cs new file mode 100644 index 00000000..40ab1b03 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/DirectoryHeader.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class DirectoryHeader + { + // All logic lives in the typed version + } + + /// + public abstract class DirectoryHeader + { + public uint SectionOffset { get; set; } + + public T? SectionCount { get; set; } + + public uint FolderOffset { get; set; } + + public T? FolderCount { get; set; } + + public uint FileOffset { get; set; } + + public T? FileCount { get; set; } + + public uint StringTableOffset { get; set; } + + public T? StringTableCount { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/DirectoryHeader4.cs b/SabreTools.Serialization/Models/SGA/DirectoryHeader4.cs new file mode 100644 index 00000000..405593f5 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/DirectoryHeader4.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class DirectoryHeader4 : DirectoryHeader { } +} diff --git a/SabreTools.Serialization/Models/SGA/DirectoryHeader5.cs b/SabreTools.Serialization/Models/SGA/DirectoryHeader5.cs new file mode 100644 index 00000000..18e6301b --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/DirectoryHeader5.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class DirectoryHeader5 : DirectoryHeader { } +} diff --git a/SabreTools.Serialization/Models/SGA/DirectoryHeader7.cs b/SabreTools.Serialization/Models/SGA/DirectoryHeader7.cs new file mode 100644 index 00000000..d0821fb5 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/DirectoryHeader7.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class DirectoryHeader7 : DirectoryHeader + { + public uint HashTableOffset { get; set; } + + public uint BlockSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/File.cs b/SabreTools.Serialization/Models/SGA/File.cs new file mode 100644 index 00000000..3d8ca532 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/File.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class File + { + public uint NameOffset { get; set; } + + public string? Name { get; set; } + + public uint Offset { get; set; } + + public uint SizeOnDisk { get; set; } + + public uint Size { get; set; } + + public uint TimeModified { get; set; } + + public byte Dummy0 { get; set; } + + public byte Type { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/File4.cs b/SabreTools.Serialization/Models/SGA/File4.cs new file mode 100644 index 00000000..73296ebb --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/File4.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class File4 : File { } +} diff --git a/SabreTools.Serialization/Models/SGA/File6.cs b/SabreTools.Serialization/Models/SGA/File6.cs new file mode 100644 index 00000000..1d221a50 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/File6.cs @@ -0,0 +1,8 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class File6 : File + { + public uint CRC32 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/File7.cs b/SabreTools.Serialization/Models/SGA/File7.cs new file mode 100644 index 00000000..96b264e8 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/File7.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class File7 : File + { + public uint CRC32 { get; set; } + + public uint HashOffset { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/FileHeader.cs b/SabreTools.Serialization/Models/SGA/FileHeader.cs new file mode 100644 index 00000000..6980ddcb --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/FileHeader.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class FileHeader + { + public string? Name { get; set; } + + public uint CRC32 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Folder.cs b/SabreTools.Serialization/Models/SGA/Folder.cs new file mode 100644 index 00000000..ed461e68 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Folder.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class Folder + { + public uint NameOffset { get; set; } + + public string? Name { get; set; } + } + + /// + public abstract class Folder : Folder + { + public T? FolderStartIndex { get; set; } + + public T? FolderEndIndex { get; set; } + + public T? FileStartIndex { get; set; } + + public T? FileEndIndex { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Folder4.cs b/SabreTools.Serialization/Models/SGA/Folder4.cs new file mode 100644 index 00000000..8366140f --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Folder4.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Folder4 : Folder { } +} diff --git a/SabreTools.Serialization/Models/SGA/Folder5.cs b/SabreTools.Serialization/Models/SGA/Folder5.cs new file mode 100644 index 00000000..45b19325 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Folder5.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Folder5 : Folder { } +} diff --git a/SabreTools.Serialization/Models/SGA/Header.cs b/SabreTools.Serialization/Models/SGA/Header.cs new file mode 100644 index 00000000..4203ba62 --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Header.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class Header + { + public string? Signature { get; set; } + + public ushort MajorVersion { get; set; } + + public ushort MinorVersion { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Header4.cs b/SabreTools.Serialization/Models/SGA/Header4.cs new file mode 100644 index 00000000..0a2cd7cd --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Header4.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Header4 : Header + { + public byte[]? FileMD5 { get; set; } + + public string? Name { get; set; } + + public byte[]? HeaderMD5 { get; set; } + + public uint HeaderLength { get; set; } + + public uint FileDataOffset { get; set; } + + public uint Dummy0 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Header6.cs b/SabreTools.Serialization/Models/SGA/Header6.cs new file mode 100644 index 00000000..d8ef407d --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Header6.cs @@ -0,0 +1,14 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Header6 : Header + { + public string? Name { get; set; } + + public uint HeaderLength { get; set; } + + public uint FileDataOffset { get; set; } + + public uint Dummy0 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Section.cs b/SabreTools.Serialization/Models/SGA/Section.cs new file mode 100644 index 00000000..9e57843e --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Section.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public abstract class Section + { + public string? Alias { get; set; } + + public string? Name { get; set; } + } + + /// + public abstract class Section : Section + { + public T? FolderStartIndex { get; set; } + + public T? FolderEndIndex { get; set; } + + public T? FileStartIndex { get; set; } + + public T? FileEndIndex { get; set; } + + public T? FolderRootIndex { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SGA/Section4.cs b/SabreTools.Serialization/Models/SGA/Section4.cs new file mode 100644 index 00000000..7b70967a --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Section4.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Section4 : Section { } +} diff --git a/SabreTools.Serialization/Models/SGA/Section5.cs b/SabreTools.Serialization/Models/SGA/Section5.cs new file mode 100644 index 00000000..2c4f8f9d --- /dev/null +++ b/SabreTools.Serialization/Models/SGA/Section5.cs @@ -0,0 +1,5 @@ +namespace SabreTools.Serialization.Models.SGA +{ + /// + public sealed class Section5 : Section { } +} diff --git a/SabreTools.Serialization/Models/SevenZip/Archive.cs b/SabreTools.Serialization/Models/SevenZip/Archive.cs new file mode 100644 index 00000000..99dd66db --- /dev/null +++ b/SabreTools.Serialization/Models/SevenZip/Archive.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.SevenZip +{ + /// + /// This is a placeholder model for future work + /// + public class Archive + { + + } +} diff --git a/SabreTools.Serialization/Models/SevenZip/Constants.cs b/SabreTools.Serialization/Models/SevenZip/Constants.cs new file mode 100644 index 00000000..c6e560c4 --- /dev/null +++ b/SabreTools.Serialization/Models/SevenZip/Constants.cs @@ -0,0 +1,7 @@ +namespace SabreTools.Serialization.Models.SevenZip +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Archive.cs b/SabreTools.Serialization/Models/TAR/Archive.cs new file mode 100644 index 00000000..a23eabed --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Archive.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.TAR +{ + public sealed class Archive + { + /// + /// 1 or more entries + /// + public Entry[]? Entries { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Block.cs b/SabreTools.Serialization/Models/TAR/Block.cs new file mode 100644 index 00000000..99a30b4f --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Block.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.TAR +{ + public sealed class Block + { + /// + /// Data + /// + /// 512 bytes + public byte[]? Data { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Constants.cs b/SabreTools.Serialization/Models/TAR/Constants.cs new file mode 100644 index 00000000..deb0d91a --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Constants.cs @@ -0,0 +1,9 @@ +namespace SabreTools.Serialization.Models.TAR +{ + public static class Constants + { + public static readonly byte[] UstarSignatureBytes = [0x75, 0x73, 0x74, 0x61, 0x72]; + + public const string UstarSignatureString = "ustar"; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Entry.cs b/SabreTools.Serialization/Models/TAR/Entry.cs new file mode 100644 index 00000000..55349626 --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Entry.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.TAR +{ + public sealed class Entry + { + /// + /// Entry header + /// + public Header? Header { get; set; } + + /// + /// 0 or more blocks representing the content + /// + public Block[]? Blocks { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Enums.cs b/SabreTools.Serialization/Models/TAR/Enums.cs new file mode 100644 index 00000000..e3b9ca3f --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Enums.cs @@ -0,0 +1,157 @@ +using System; + +namespace SabreTools.Serialization.Models.TAR +{ + [Flags] + public enum Mode : ushort + { + /// + /// Execute/search by other + /// + TOEXEC = 0x0001, + + /// + /// Write by other + /// + TOWRITE = 0x0002, + + /// + /// Read by other + /// + TOREAD = 0x0004, + + /// + /// Execute/search by group + /// + TGEXEC = 0x0008, + + /// + /// Write by group + /// + TGWRITE = 0x0010, + + /// + /// Read by group + /// + TGREAD = 0x0020, + + /// + /// Execute/search by owner + /// + TUEXEC = 0x0040, + + /// + /// Write by owner + /// + TUWRITE = 0x0080, + + /// + /// Read by owner + /// + TUREAD = 0x0100, + + /// + /// Reserved + /// + TSVTX = 0x0200, + + /// + /// Set GID on execution + /// + TSGID = 0x0400, + + /// + /// Set UID on execution + /// + TSUID = 0x0800, + } + + public enum TypeFlag : byte + { + /// + /// Regular file + /// + REGTYPE = (byte)'0', + + /// + /// Regular file + /// + AREGTYPE = 0, + + /// + /// Hard link + /// + LNKTYPE = (byte)'1', + + /// + /// Symbolic link + /// + SYMTYPE = (byte)'2', + + /// + /// Character special + /// + CHRTYPE = (byte)'3', + + /// + /// Block special + /// + BLKTYPE = (byte)'4', + + /// + /// Directory + /// + DIRTYPE = (byte)'5', + + /// + /// FIFO + /// + FIFOTYPE = (byte)'6', + + /// + /// Contiguous file + /// + CONTTYPE = (byte)'7', + + /// + /// Global extended header with meta data (POSIX.1-2001) + /// + XHDTYPE = (byte)'g', + + /// + /// Extended header with metadata for the next file in the archive (POSIX.1-2001) + /// + XGLTYPE = (byte)'x', + + #region Vendor-Specific Extensions (POSIX.1-1988) + + VendorSpecificA = (byte)'A', + VendorSpecificB = (byte)'B', + VendorSpecificC = (byte)'C', + VendorSpecificD = (byte)'D', + VendorSpecificE = (byte)'E', + VendorSpecificF = (byte)'F', + VendorSpecificG = (byte)'G', + VendorSpecificH = (byte)'H', + VendorSpecificI = (byte)'I', + VendorSpecificJ = (byte)'J', + VendorSpecificK = (byte)'K', + VendorSpecificL = (byte)'L', + VendorSpecificM = (byte)'M', + VendorSpecificN = (byte)'N', + VendorSpecificO = (byte)'O', + VendorSpecificP = (byte)'P', + VendorSpecificQ = (byte)'Q', + VendorSpecificR = (byte)'R', + VendorSpecificS = (byte)'S', + VendorSpecificT = (byte)'T', + VendorSpecificU = (byte)'U', + VendorSpecificV = (byte)'V', + VendorSpecificW = (byte)'W', + VendorSpecificX = (byte)'X', + VendorSpecificY = (byte)'Y', + VendorSpecificZ = (byte)'Z', + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/TAR/Header.cs b/SabreTools.Serialization/Models/TAR/Header.cs new file mode 100644 index 00000000..5c7f2412 --- /dev/null +++ b/SabreTools.Serialization/Models/TAR/Header.cs @@ -0,0 +1,117 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.TAR +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// File name without a forward slash + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string? FileName; + + /// + /// File mode + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? Mode; + + /// + /// Owner's numeric user ID + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? UID; + + /// + /// Owner's numeric group ID + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? GID; + + /// + /// File size in bytes + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)] + public string? Size; + + /// + /// Last modification time in numeric Unix time format + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)] + public string? ModifiedTime; + + /// + /// Checksum for header record + /// + /// Octal string representation + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? Checksum; + + /// + /// Link indicator (file type) / Type flag + /// + public TypeFlag TypeFlag; + + /// + /// Linked path name or file name + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string? LinkName; + + #region USTAR Extension + + /// + /// UStar indicator, "ustar" + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)] + public string? Magic; + + /// + /// UStar version, "00" + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)] + public string? Version; + + /// + /// Owner user name + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string? UserName; + + /// + /// Owner group name + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string? GroupName; + + /// + /// Device major number + /// + /// Octal string representation(?) + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? DevMajor; + + /// + /// Device minor number + /// + /// Octal string representation(?) + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string? DevMinor; + + /// + /// Path name without trailing slashes + /// + /// 155 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 155)] + public string? Prefix; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/VPK/ArchiveHash.cs b/SabreTools.Serialization/Models/VPK/ArchiveHash.cs new file mode 100644 index 00000000..ed41e115 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/ArchiveHash.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ArchiveHash + { + public uint ArchiveIndex; + + public uint ArchiveOffset; + + public uint Length; + + /// + /// MD5 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10)] + public byte[]? Hash; + } +} diff --git a/SabreTools.Serialization/Models/VPK/ArchiveMD5SectionEntry.cs b/SabreTools.Serialization/Models/VPK/ArchiveMD5SectionEntry.cs new file mode 100644 index 00000000..60f5d890 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/ArchiveMD5SectionEntry.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ArchiveMD5SectionEntry + { + public uint ArchiveIndex; + + /// + /// Where to start reading bytes + /// + public uint StartingOffset; + + /// + /// How many bytes to check + /// + public uint Count; + + /// + /// Expected checksum + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? MD5Checksum = new byte[16]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/VPK/Constants.cs b/SabreTools.Serialization/Models/VPK/Constants.cs new file mode 100644 index 00000000..db18d951 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/Constants.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.VPK +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x34, 0x12, 0xaa, 0x55]; + + public static readonly string SignatureString = System.Text.Encoding.ASCII.GetString(SignatureBytes); + + public const uint SignatureUInt32 = 0x55aa1234; + + /// + /// Index indicating that there is no archive + /// + public const int HL_VPK_NO_ARCHIVE = 0x7fff; + + /// + /// Length of a VPK checksum in bytes + /// + public const int HL_VPK_CHECKSUM_LENGTH = 0x00008000; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/VPK/DirectoryEntry.cs b/SabreTools.Serialization/Models/VPK/DirectoryEntry.cs new file mode 100644 index 00000000..9e8ecf44 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/DirectoryEntry.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryEntry + { + /// + /// A 32bit CRC of the file's data. + /// + public uint CRC; + + /// + /// The number of bytes contained in the index file. + /// + public ushort PreloadBytes; + + /// + /// A zero based index of the archive this file's data is contained in. + /// If 0x7fff, the data follows the directory. + /// + public ushort ArchiveIndex; + + /// + /// If ArchiveIndex is 0x7fff, the offset of the file data relative to the + /// end of the directory (see the header for more details). + /// Otherwise, the offset of the data from the start of the specified archive. + /// + public uint EntryOffset; + + /// + /// If zero, the entire file is stored in the preload data. + /// Otherwise, the number of bytes stored starting at EntryOffset. + /// + public uint EntryLength; + + /// + /// Always 0xffff. + /// + public ushort Dummy0; + } +} diff --git a/SabreTools.Serialization/Models/VPK/DirectoryItem.cs b/SabreTools.Serialization/Models/VPK/DirectoryItem.cs new file mode 100644 index 00000000..17b36597 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/DirectoryItem.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.VPK +{ + /// + /// + public sealed class DirectoryItem + { + public string? Extension { get; set; } + + public string? Path { get; set; } + + public string? Name { get; set; } + + public DirectoryEntry? DirectoryEntry { get; set; } + + public byte[]? PreloadData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/VPK/ExtendedHeader.cs b/SabreTools.Serialization/Models/VPK/ExtendedHeader.cs new file mode 100644 index 00000000..4f40ff85 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/ExtendedHeader.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + /// Added in version 2. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ExtendedHeader + { + /// + /// How many bytes of file content are stored in this + /// VPK file (0 in CSGO) + /// + public uint FileDataSectionSize; + + /// + /// The size, in bytes, of the section containing MD5 + /// checksums for external archive content + /// + public uint ArchiveMD5SectionSize; + + /// + /// The size, in bytes, of the section containing MD5 + /// checksums for content in this file (should always be 48) + /// + public uint OtherMD5SectionSize; + + /// + /// The size, in bytes, of the section containing the public + /// key and signature. This is either 0 (CSGO & The Ship) or + /// 296 (HL2, HL2:DM, HL2:EP1, HL2:EP2, HL2:LC, TF2, DOD:S & CS:S) + /// + public uint SignatureSectionSize; + } +} diff --git a/SabreTools.Serialization/Models/VPK/File.cs b/SabreTools.Serialization/Models/VPK/File.cs new file mode 100644 index 00000000..fb535ecd --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/File.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.VPK +{ + /// + /// Valve Package File + /// + /// + public sealed class File + { + /// + /// Header data + /// + public Header? Header { get; set; } + + /// + /// Extended header data + /// + public ExtendedHeader? ExtendedHeader { get; set; } + + /// + /// Archive hashes data + /// + public ArchiveHash[]? ArchiveHashes { get; set; } + + /// + /// Directory items data + /// + public DirectoryItem[]? DirectoryItems { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/VPK/Header.cs b/SabreTools.Serialization/Models/VPK/Header.cs new file mode 100644 index 00000000..57892ce5 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/Header.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Header + { + /// + /// Always 0x55aa1234. + /// + public uint Signature; + + public uint Version; + + /// + /// The size, in bytes, of the directory tree + /// + public uint TreeSize; + } +} diff --git a/SabreTools.Serialization/Models/VPK/OtherMD5Section.cs b/SabreTools.Serialization/Models/VPK/OtherMD5Section.cs new file mode 100644 index 00000000..f4e3e8d9 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/OtherMD5Section.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class OtherMD5Section + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? TreeChecksum = new byte[16]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? ArchiveMD5SectionChecksum = new byte[16]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? WholeFileChecksum = new byte[16]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/VPK/SignatureSection.cs b/SabreTools.Serialization/Models/VPK/SignatureSection.cs new file mode 100644 index 00000000..33d2b442 --- /dev/null +++ b/SabreTools.Serialization/Models/VPK/SignatureSection.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class SignatureSection + { + /// + /// Always seen as 160 (0xA0) bytes + /// + public uint PublicKeySize; + + /// + /// + /// + public byte[]? PublicKey; + + /// + /// Always seen as 128 (0x80) bytes + /// + public uint SignatureSize; + + /// + /// + /// + public byte[]? Signature; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WAD3/CharInfo.cs b/SabreTools.Serialization/Models/WAD3/CharInfo.cs new file mode 100644 index 00000000..d17e32f8 --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/CharInfo.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class CharInfo + { + public ushort StartOffset; + + public ushort CharWidth; + } +} diff --git a/SabreTools.Serialization/Models/WAD3/Constants.cs b/SabreTools.Serialization/Models/WAD3/Constants.cs new file mode 100644 index 00000000..656e91a1 --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x57, 0x41, 0x44, 0x33]; + + public const string SignatureString = "WAD3"; + + public const uint SignatureUInt32 = 0x33444157; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WAD3/DirEntry.cs b/SabreTools.Serialization/Models/WAD3/DirEntry.cs new file mode 100644 index 00000000..c8257fa7 --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/DirEntry.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class DirEntry + { + /// + /// Offset from the beginning of the WAD3 data + /// + public uint Offset; + + /// + /// The entry's size in the archive in bytes + /// + public uint DiskLength; + + /// + /// The entry's uncompressed size + /// + public uint Length; + + /// + /// File type of the entry + /// + public FileType Type; + + /// + /// Whether the file was compressed + /// + /// Actually a boolean value + public byte Compression; + + /// + /// Padding + /// + public ushort Padding; + + /// + /// Null-terminated texture name + /// + /// 16 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string? Name; + } +} diff --git a/SabreTools.Serialization/Models/WAD3/Enums.cs b/SabreTools.Serialization/Models/WAD3/Enums.cs new file mode 100644 index 00000000..4a2f47dd --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/Enums.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + public enum FileType : byte + { + /// + /// spraydecal (0x40): Same as . + /// Only found in entry LOGO (or {LOGO) in tempdecal.wad + /// + Spraydecal = 0x40, + + /// + /// qpic (0x42): A simple image of any size. + /// + Qpic = 0x42, + + /// + /// miptex (0x43): World texture with dimensions that are multiple-of-16 + /// and 4 mipmaps. This is the typical entry type. + /// + Miptex = 0x43, + + /// + /// font (0x46): Fixed-height font for 256 ASCII characters. + /// + Font = 0x46, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WAD3/File.cs b/SabreTools.Serialization/Models/WAD3/File.cs new file mode 100644 index 00000000..dcdf3b9d --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/File.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + /// Half-Life Texture Package File + /// + /// + public sealed class File + { + /// + /// Deserialized header data + /// + public Header? Header { get; set; } + + /// + /// Deserialized dir entry data + /// + public DirEntry[]? DirEntries { get; set; } + + /// + /// Deserialized file entry data + /// + public FileEntry[]? FileEntries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WAD3/FileEntry.cs b/SabreTools.Serialization/Models/WAD3/FileEntry.cs new file mode 100644 index 00000000..351ba2cc --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/FileEntry.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + /// qlumpy always align entries to the DWORD (=4 bytes) boundary + /// (i.e. next integer multiples of 4 offset from start of file) + /// + public abstract class FileEntry + { + // No shared fields between types + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WAD3/Font.cs b/SabreTools.Serialization/Models/WAD3/Font.cs new file mode 100644 index 00000000..1aba1cbe --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/Font.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Font : FileEntry + { + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Width; + + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Height; + + public uint RowCount; + + public uint RowHeight; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public CharInfo[] FontInfo = new CharInfo[256]; + + /// [width][height] + public byte[][]? Data; + + /// + /// Number of colors used in the palette (always 256 for GoldSrc) + /// + public ushort ColorsUsed; + + /// + /// The color palette for the mipmaps (always 256 * 3 = 768 for GoldSrc) + /// + /// [ColorsUsed][3] + public byte[][]? Palette { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WAD3/Header.cs b/SabreTools.Serialization/Models/WAD3/Header.cs new file mode 100644 index 00000000..9769b9ea --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/Header.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// "WAD3" + /// + /// 4 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + /// + /// Number of Directory entries + /// + public uint NumDirs; + + /// + /// Offset from the WAD3 data's beginning for first Directory entry + /// + public uint DirOffset; + } +} diff --git a/SabreTools.Serialization/Models/WAD3/MipMap.cs b/SabreTools.Serialization/Models/WAD3/MipMap.cs new file mode 100644 index 00000000..8f4b702f --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/MipMap.cs @@ -0,0 +1,12 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + public sealed class MipMap + { + /// + /// Raw image data. Each byte points to an index in the palette + /// + /// [width][height] + public byte[][]? Data { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WAD3/MipTex.cs b/SabreTools.Serialization/Models/WAD3/MipTex.cs new file mode 100644 index 00000000..8933be42 --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/MipTex.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + public sealed class MipTex : FileEntry + { + /// + /// Null-terminated texture name + /// + /// 16 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string? Name; + + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Width; + + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Height; + + /// + /// Offset from start of this struct to each mipmap level's image + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public uint[] MipOffsets = new uint[4]; + + /// + /// One MipMap for each mipmap level + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public MipMap[] MipImages = new MipMap[4]; + + /// + /// Number of colors used in the palette (always 256 for GoldSrc) + /// + public ushort ColorsUsed; + + /// + /// The color palette for the mipmaps (always 256 * 3 = 768 for GoldSrc) + /// + /// [ColorsUsed][3] + public byte[][]? Palette { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WAD3/QpicImage.cs b/SabreTools.Serialization/Models/WAD3/QpicImage.cs new file mode 100644 index 00000000..60017aa7 --- /dev/null +++ b/SabreTools.Serialization/Models/WAD3/QpicImage.cs @@ -0,0 +1,33 @@ +namespace SabreTools.Serialization.Models.WAD3 +{ + /// + public sealed class QpicImage : FileEntry + { + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Width; + + /// + /// Dimensions of the texture (must be divisible by 16) + /// + public uint Height; + + /// + /// Raw image data. Each byte points to an index in the palette + /// + /// [height][width] + public byte[][]? Data { get; set; } + + /// + /// Number of colors used in the palette (always 256 for GoldSrc) + /// + public ushort ColorsUsed; + + /// + /// The color palette for the mipmaps (always 256 * 3 = 768 for GoldSrc) + /// + /// [ColorsUsed][3] + public byte[][]? Palette { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/XZ/Archive.cs b/SabreTools.Serialization/Models/XZ/Archive.cs new file mode 100644 index 00000000..2d8ab401 --- /dev/null +++ b/SabreTools.Serialization/Models/XZ/Archive.cs @@ -0,0 +1,10 @@ +namespace SabreTools.Serialization.Models.XZ +{ + /// + /// This is a placeholder model for future work + /// + public class Archive + { + + } +} diff --git a/SabreTools.Serialization/Models/XZ/Constants.cs b/SabreTools.Serialization/Models/XZ/Constants.cs new file mode 100644 index 00000000..1015e4e2 --- /dev/null +++ b/SabreTools.Serialization/Models/XZ/Constants.cs @@ -0,0 +1,7 @@ +namespace SabreTools.Serialization.Models.XZ +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/XZP/Constants.cs b/SabreTools.Serialization/Models/XZP/Constants.cs new file mode 100644 index 00000000..b798eecf --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/Constants.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.XZP +{ + public static class Constants + { + public static readonly byte[] HeaderSignatureBytes = [0x70, 0x69, 0x5a, 0x78]; + + public const string HeaderSignatureString = "piZx"; + + public const uint HeaderSignatureUInt32 = 0x785a6970; + + public static readonly byte[] FooterSignatureBytes = [0x74, 0x46, 0x7a, 0x58]; + + public const string FooterSignatureString = "tFzX"; + + public const uint FooterSignatureUInt32 = 0x587a4674; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/XZP/DirectoryEntry.cs b/SabreTools.Serialization/Models/XZP/DirectoryEntry.cs new file mode 100644 index 00000000..5b36c6fc --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/DirectoryEntry.cs @@ -0,0 +1,15 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.XZP +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryEntry + { + public uint FileNameCRC; + + public uint EntryLength; + + public uint EntryOffset; + } +} diff --git a/SabreTools.Serialization/Models/XZP/DirectoryItem.cs b/SabreTools.Serialization/Models/XZP/DirectoryItem.cs new file mode 100644 index 00000000..2d02d565 --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/DirectoryItem.cs @@ -0,0 +1,14 @@ +namespace SabreTools.Serialization.Models.XZP +{ + /// + public sealed class DirectoryItem + { + public uint FileNameCRC { get; set; } + + public uint NameOffset { get; set; } + + public string? Name { get; set; } + + public uint TimeCreated { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/XZP/DirectoryMapping.cs b/SabreTools.Serialization/Models/XZP/DirectoryMapping.cs new file mode 100644 index 00000000..0d38390f --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/DirectoryMapping.cs @@ -0,0 +1,11 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.XZP +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryMapping + { + public ushort PreloadDirectoryEntryIndex; + } +} diff --git a/SabreTools.Serialization/Models/XZP/File.cs b/SabreTools.Serialization/Models/XZP/File.cs new file mode 100644 index 00000000..902fe701 --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/File.cs @@ -0,0 +1,39 @@ +namespace SabreTools.Serialization.Models.XZP +{ + /// + /// XBox Package File + /// + /// + public sealed class File + { + /// + /// Header data + /// + public Header? Header { get; set; } + + /// + /// Directory entries data + /// + public DirectoryEntry[]? DirectoryEntries { get; set; } + + /// + /// Preload directory entries data + /// + public DirectoryEntry[]? PreloadDirectoryEntries { get; set; } + + /// + /// Preload directory mappings data + /// + public DirectoryMapping[]? PreloadDirectoryMappings { get; set; } + + /// + /// Directory items data + /// + public DirectoryItem[]? DirectoryItems { get; set; } + + /// + /// Footer data + /// + public Footer? Footer { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/XZP/Footer.cs b/SabreTools.Serialization/Models/XZP/Footer.cs new file mode 100644 index 00000000..3d45a3ec --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/Footer.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.XZP +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Footer + { + public uint FileLength; + + /// + /// "tFzX" + /// + /// 4 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + } +} diff --git a/SabreTools.Serialization/Models/XZP/Header.cs b/SabreTools.Serialization/Models/XZP/Header.cs new file mode 100644 index 00000000..9395ab56 --- /dev/null +++ b/SabreTools.Serialization/Models/XZP/Header.cs @@ -0,0 +1,32 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.XZP +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class Header + { + /// + /// "piZx" + /// + /// 4 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Signature; + + public uint Version; + + public uint PreloadDirectoryEntryCount; + + public uint DirectoryEntryCount; + + public uint PreloadBytes; + + public uint HeaderLength; + + public uint DirectoryItemCount; + + public uint DirectoryItemOffset; + + public uint DirectoryItemLength; + } +} diff --git a/SabreTools.Serialization/Printers/BFPK.cs b/SabreTools.Serialization/Printers/BFPK.cs index 4e07e892..3b4e870e 100644 --- a/SabreTools.Serialization/Printers/BFPK.cs +++ b/SabreTools.Serialization/Printers/BFPK.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.BFPK; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.BFPK; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/BSP.cs b/SabreTools.Serialization/Printers/BSP.cs index 073b34b5..7fac28f8 100644 --- a/SabreTools.Serialization/Printers/BSP.cs +++ b/SabreTools.Serialization/Printers/BSP.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.BSP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/GCF.cs b/SabreTools.Serialization/Printers/GCF.cs index ac491f5a..1ef6f847 100644 --- a/SabreTools.Serialization/Printers/GCF.cs +++ b/SabreTools.Serialization/Printers/GCF.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text; -using SabreTools.Models.GCF; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.GCF; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/GZip.cs b/SabreTools.Serialization/Printers/GZip.cs index 1737e3a0..1c7e1083 100644 --- a/SabreTools.Serialization/Printers/GZip.cs +++ b/SabreTools.Serialization/Printers/GZip.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.GZIP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.GZIP; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Printers/InstallShieldArchiveV3.cs index 45e9e3cf..bec31563 100644 --- a/SabreTools.Serialization/Printers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Printers/InstallShieldArchiveV3.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.InstallShieldArchiveV3; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.InstallShieldArchiveV3; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/InstallShieldCabinet.cs b/SabreTools.Serialization/Printers/InstallShieldCabinet.cs index 0ecfe0ca..a325afb7 100644 --- a/SabreTools.Serialization/Printers/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Printers/InstallShieldCabinet.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text; -using SabreTools.Models.InstallShieldCabinet; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.InstallShieldCabinet; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/LZKWAJ.cs b/SabreTools.Serialization/Printers/LZKWAJ.cs index a82ef58d..88607ee7 100644 --- a/SabreTools.Serialization/Printers/LZKWAJ.cs +++ b/SabreTools.Serialization/Printers/LZKWAJ.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.LZ; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/LZQBasic.cs b/SabreTools.Serialization/Printers/LZQBasic.cs index cafea9f3..fd924701 100644 --- a/SabreTools.Serialization/Printers/LZQBasic.cs +++ b/SabreTools.Serialization/Printers/LZQBasic.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.LZ; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/LZSZDD.cs b/SabreTools.Serialization/Printers/LZSZDD.cs index b0752046..49802d1e 100644 --- a/SabreTools.Serialization/Printers/LZSZDD.cs +++ b/SabreTools.Serialization/Printers/LZSZDD.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.LZ; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/MicrosoftCabinet.cs b/SabreTools.Serialization/Printers/MicrosoftCabinet.cs index 738a1d6e..9e70a6d5 100644 --- a/SabreTools.Serialization/Printers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Printers/MicrosoftCabinet.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.MicrosoftCabinet; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.MicrosoftCabinet; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/MoPaQ.cs b/SabreTools.Serialization/Printers/MoPaQ.cs index d6efb61e..77640458 100644 --- a/SabreTools.Serialization/Printers/MoPaQ.cs +++ b/SabreTools.Serialization/Printers/MoPaQ.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.MoPaQ; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.MoPaQ; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/NCF.cs b/SabreTools.Serialization/Printers/NCF.cs index 22ff7bfa..118fa897 100644 --- a/SabreTools.Serialization/Printers/NCF.cs +++ b/SabreTools.Serialization/Printers/NCF.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text; -using SabreTools.Models.NCF; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.NCF; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/PAK.cs b/SabreTools.Serialization/Printers/PAK.cs index 567f51a7..0def4f6f 100644 --- a/SabreTools.Serialization/Printers/PAK.cs +++ b/SabreTools.Serialization/Printers/PAK.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.PAK; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.PAK; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/PFF.cs b/SabreTools.Serialization/Printers/PFF.cs index 64fc6856..eda39f44 100644 --- a/SabreTools.Serialization/Printers/PFF.cs +++ b/SabreTools.Serialization/Printers/PFF.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.PFF; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.PFF; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/PKZIP.cs b/SabreTools.Serialization/Printers/PKZIP.cs index f515ebcb..994bae5a 100644 --- a/SabreTools.Serialization/Printers/PKZIP.cs +++ b/SabreTools.Serialization/Printers/PKZIP.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.PKZIP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.PKZIP; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/PortableExecutable.cs b/SabreTools.Serialization/Printers/PortableExecutable.cs index 415da490..6364b8b0 100644 --- a/SabreTools.Serialization/Printers/PortableExecutable.cs +++ b/SabreTools.Serialization/Printers/PortableExecutable.cs @@ -1362,11 +1362,11 @@ namespace SabreTools.Serialization.Printers { builder.AppendLine($"{padding}Data: [Embedded spanned PKZIP file]"); // TODO: Parse this out and print separately } - else if (magic.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) { builder.AppendLine($"{padding}Data: [Embedded RAR file]"); // TODO: Parse this out and print separately } - else if (magic.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) { builder.AppendLine($"{padding}Data: [Embedded RAR5 file]"); // TODO: Parse this out and print separately } @@ -1848,11 +1848,11 @@ namespace SabreTools.Serialization.Printers { builder.AppendLine($"{padding}Data: [Embedded spanned PKZIP file]"); // TODO: Parse this out and print separately } - else if (magic.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) { builder.AppendLine($"{padding}Data: [Embedded RAR file]"); // TODO: Parse this out and print separately } - else if (magic.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) { builder.AppendLine($"{padding}Data: [Embedded RAR5 file]"); // TODO: Parse this out and print separately } diff --git a/SabreTools.Serialization/Printers/Quantum.cs b/SabreTools.Serialization/Printers/Quantum.cs index cf99d2df..15303df8 100644 --- a/SabreTools.Serialization/Printers/Quantum.cs +++ b/SabreTools.Serialization/Printers/Quantum.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.Quantum; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.Quantum; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/SGA.cs b/SabreTools.Serialization/Printers/SGA.cs index 475afbd5..53fd1359 100644 --- a/SabreTools.Serialization/Printers/SGA.cs +++ b/SabreTools.Serialization/Printers/SGA.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.SGA; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.SGA; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/TapeArchive.cs b/SabreTools.Serialization/Printers/TapeArchive.cs index b111a604..41bc6293 100644 --- a/SabreTools.Serialization/Printers/TapeArchive.cs +++ b/SabreTools.Serialization/Printers/TapeArchive.cs @@ -1,7 +1,6 @@ -using System.Collections.Generic; using System.Text; -using SabreTools.Models.TAR; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.TAR; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/VBSP.cs b/SabreTools.Serialization/Printers/VBSP.cs index d16ac6b8..23137134 100644 --- a/SabreTools.Serialization/Printers/VBSP.cs +++ b/SabreTools.Serialization/Printers/VBSP.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.BSP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/VPK.cs b/SabreTools.Serialization/Printers/VPK.cs index 6589eef6..bb73919f 100644 --- a/SabreTools.Serialization/Printers/VPK.cs +++ b/SabreTools.Serialization/Printers/VPK.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.VPK; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.VPK; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/WAD3.cs b/SabreTools.Serialization/Printers/WAD3.cs index 1e3a2724..baadef8e 100644 --- a/SabreTools.Serialization/Printers/WAD3.cs +++ b/SabreTools.Serialization/Printers/WAD3.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.WAD3; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.WAD3; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/XZP.cs b/SabreTools.Serialization/Printers/XZP.cs index 623b5901..eb4f98df 100644 --- a/SabreTools.Serialization/Printers/XZP.cs +++ b/SabreTools.Serialization/Printers/XZP.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.XZP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.XZP; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/WrapperFactory.cs b/SabreTools.Serialization/WrapperFactory.cs index e76262da..9d89370e 100644 --- a/SabreTools.Serialization/WrapperFactory.cs +++ b/SabreTools.Serialization/WrapperFactory.cs @@ -169,7 +169,7 @@ namespace SabreTools.Serialization #region BFPK - if (magic.StartsWith(SabreTools.Models.BFPK.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.BFPK.Constants.SignatureBytes)) return WrapperType.BFPK; #endregion @@ -191,7 +191,7 @@ namespace SabreTools.Serialization #region BZip2 - if (magic.StartsWith(SabreTools.Models.BZip2.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.BZip2.Constants.SignatureBytes)) return WrapperType.BZip2; if (extension.Equals("bz2", StringComparison.OrdinalIgnoreCase)) @@ -296,7 +296,7 @@ namespace SabreTools.Serialization #region GZip - if (magic.StartsWith(new byte[] { SabreTools.Models.GZIP.Constants.ID1, SabreTools.Models.GZIP.Constants.ID2 })) + if (magic.StartsWith(new byte[] { SabreTools.Serialization.Models.GZIP.Constants.ID1, SabreTools.Serialization.Models.GZIP.Constants.ID2 })) return WrapperType.GZip; if (extension.Equals("gz", StringComparison.OrdinalIgnoreCase)) @@ -313,7 +313,7 @@ namespace SabreTools.Serialization #region InstallShieldArchiveV3 - if (magic.StartsWith(SabreTools.Models.InstallShieldArchiveV3.Constants.HeaderSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.InstallShieldArchiveV3.Constants.HeaderSignatureBytes)) return WrapperType.InstallShieldArchiveV3; if (extension.Equals("z", StringComparison.OrdinalIgnoreCase)) @@ -323,7 +323,7 @@ namespace SabreTools.Serialization #region InstallShieldCAB - if (magic.StartsWith(SabreTools.Models.InstallShieldCabinet.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.InstallShieldCabinet.Constants.SignatureBytes)) return WrapperType.InstallShieldCAB; // Both InstallShieldCAB and MicrosoftCAB share the same extension @@ -339,20 +339,20 @@ namespace SabreTools.Serialization #region LZ - if (magic.StartsWith(SabreTools.Models.LZ.Constants.KWAJSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.LZ.Constants.KWAJSignatureBytes)) return WrapperType.LZKWAJ; - if (magic.StartsWith(SabreTools.Models.LZ.Constants.QBasicSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.LZ.Constants.QBasicSignatureBytes)) return WrapperType.LZQBasic; - if (magic.StartsWith(SabreTools.Models.LZ.Constants.SZDDSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.LZ.Constants.SZDDSignatureBytes)) return WrapperType.LZSZDD; #endregion #region MicrosoftCAB - if (magic.StartsWith(SabreTools.Models.MicrosoftCabinet.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.MicrosoftCabinet.Constants.SignatureBytes)) return WrapperType.MicrosoftCAB; // Both InstallShieldCAB and MicrosoftCAB share the same extension @@ -361,10 +361,10 @@ namespace SabreTools.Serialization #region MoPaQ - if (magic.StartsWith(SabreTools.Models.MoPaQ.Constants.ArchiveHeaderSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.MoPaQ.Constants.ArchiveHeaderSignatureBytes)) return WrapperType.MoPaQ; - if (magic.StartsWith(SabreTools.Models.MoPaQ.Constants.UserDataSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.MoPaQ.Constants.UserDataSignatureBytes)) return WrapperType.MoPaQ; if (extension.Equals("mpq", StringComparison.OrdinalIgnoreCase)) @@ -420,7 +420,7 @@ namespace SabreTools.Serialization #region PAK - if (magic.StartsWith(SabreTools.Models.PAK.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.PAK.Constants.SignatureBytes)) return WrapperType.PAK; // Both PAK and Quantum share one extension @@ -461,17 +461,17 @@ namespace SabreTools.Serialization return WrapperType.PKZIP; // PKZIP - if (magic.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) return WrapperType.PKZIP; // PKZIP (Empty Archive) - if (magic.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) return WrapperType.PKZIP; - else if (magic.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) return WrapperType.PKZIP; // PKZIP (Spanned Archive) - if (magic.StartsWith(SabreTools.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) return WrapperType.PKZIP; // PKZIP @@ -574,7 +574,7 @@ namespace SabreTools.Serialization #region Quantum - if (magic.StartsWith(SabreTools.Models.Quantum.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.Quantum.Constants.SignatureBytes)) return WrapperType.Quantum; if (extension.Equals("q", StringComparison.OrdinalIgnoreCase)) @@ -589,11 +589,11 @@ namespace SabreTools.Serialization #region RAR // RAR archive version 1.50 onwards - if (magic.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) return WrapperType.RAR; // RAR archive version 5.0 onwards - if (magic.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) return WrapperType.RAR; if (extension.Equals("rar", StringComparison.OrdinalIgnoreCase)) @@ -624,7 +624,7 @@ namespace SabreTools.Serialization #region SevenZip - if (magic.StartsWith(SabreTools.Models.SevenZip.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.SevenZip.Constants.SignatureBytes)) return WrapperType.SevenZip; if (extension.Equals("7z", StringComparison.OrdinalIgnoreCase)) @@ -642,7 +642,7 @@ namespace SabreTools.Serialization #region SGA - if (magic.StartsWith(SabreTools.Models.SGA.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.SGA.Constants.SignatureBytes)) return WrapperType.SGA; if (extension.Equals("sga", StringComparison.OrdinalIgnoreCase)) @@ -756,7 +756,7 @@ namespace SabreTools.Serialization #region VBSP - if (magic.StartsWith(SabreTools.Models.BSP.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.BSP.Constants.SignatureBytes)) return WrapperType.VBSP; // Shares an extension with BSP @@ -767,7 +767,7 @@ namespace SabreTools.Serialization #region VPK - if (magic.StartsWith(SabreTools.Models.VPK.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.VPK.Constants.SignatureBytes)) return WrapperType.VPK; // Common extension so this cannot be used accurately @@ -778,7 +778,7 @@ namespace SabreTools.Serialization #region WAD - if (magic.StartsWith(SabreTools.Models.WAD3.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.WAD3.Constants.SignatureBytes)) return WrapperType.WAD; // Common extension so this cannot be used accurately @@ -789,7 +789,7 @@ namespace SabreTools.Serialization #region XZ - if (magic.StartsWith(SabreTools.Models.XZ.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.XZ.Constants.SignatureBytes)) return WrapperType.XZ; if (extension.Equals("xz", StringComparison.OrdinalIgnoreCase)) @@ -799,7 +799,7 @@ namespace SabreTools.Serialization #region XZP - if (magic.StartsWith(SabreTools.Models.XZP.Constants.HeaderSignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.XZP.Constants.HeaderSignatureBytes)) return WrapperType.XZP; if (extension.Equals("xzp", StringComparison.OrdinalIgnoreCase)) diff --git a/SabreTools.Serialization/Wrappers/BFPK.cs b/SabreTools.Serialization/Wrappers/BFPK.cs index 8ebdd728..fb4daac4 100644 --- a/SabreTools.Serialization/Wrappers/BFPK.cs +++ b/SabreTools.Serialization/Wrappers/BFPK.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.BFPK; +using SabreTools.Serialization.Models.BFPK; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/BSP.Extraction.cs b/SabreTools.Serialization/Wrappers/BSP.Extraction.cs index 9fb5141e..76091057 100644 --- a/SabreTools.Serialization/Wrappers/BSP.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/BSP.Extraction.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using SabreTools.Models.BSP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/BSP.cs b/SabreTools.Serialization/Wrappers/BSP.cs index 73cd1396..a4a31043 100644 --- a/SabreTools.Serialization/Wrappers/BSP.cs +++ b/SabreTools.Serialization/Wrappers/BSP.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.BSP; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/BZip2.cs b/SabreTools.Serialization/Wrappers/BZip2.cs index 31a22d49..72f1ffbf 100644 --- a/SabreTools.Serialization/Wrappers/BZip2.cs +++ b/SabreTools.Serialization/Wrappers/BZip2.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.BZip2; +using SabreTools.Serialization.Models.BZip2; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/GCF.cs b/SabreTools.Serialization/Wrappers/GCF.cs index 41841ed1..8dcfec27 100644 --- a/SabreTools.Serialization/Wrappers/GCF.cs +++ b/SabreTools.Serialization/Wrappers/GCF.cs @@ -3,7 +3,7 @@ using System.IO; namespace SabreTools.Serialization.Wrappers { - public partial class GCF : WrapperBase + public partial class GCF : WrapperBase { #region Descriptive Properties @@ -39,9 +39,9 @@ namespace SabreTools.Serialization.Wrappers // If we have a directory, skip for now #if NET20 || NET35 - if ((directoryEntry.DirectoryFlags & SabreTools.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_FILE) == 0) + if ((directoryEntry.DirectoryFlags & SabreTools.Serialization.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_FILE) == 0) #else - if (!directoryEntry.DirectoryFlags.HasFlag(SabreTools.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_FILE)) + if (!directoryEntry.DirectoryFlags.HasFlag(SabreTools.Serialization.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_FILE)) #endif continue; @@ -50,13 +50,13 @@ namespace SabreTools.Serialization.Wrappers { Size = directoryEntry.ItemSize, #if NET20 || NET35 - Encrypted = (directoryEntry.DirectoryFlags & SabreTools.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED) != 0, + Encrypted = (directoryEntry.DirectoryFlags & SabreTools.Serialization.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED) != 0, #else - Encrypted = directoryEntry.DirectoryFlags.HasFlag(SabreTools.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED), + Encrypted = directoryEntry.DirectoryFlags.HasFlag(SabreTools.Serialization.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED), #endif }; var pathParts = new List { Model.DirectoryNames![directoryEntry.NameOffset] ?? string.Empty }; - var blockEntries = new List(); + var blockEntries = new List(); // Traverse the parent tree uint index = directoryEntry.ParentIndex; @@ -164,22 +164,22 @@ namespace SabreTools.Serialization.Wrappers #region Constructors /// - public GCF(SabreTools.Models.GCF.File model, byte[] data) : base(model, data) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, byte[] data) : base(model, data) { } /// - public GCF(SabreTools.Models.GCF.File model, byte[] data, int offset) : base(model, data, offset) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public GCF(SabreTools.Models.GCF.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public GCF(SabreTools.Models.GCF.File model, Stream data) : base(model, data) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, Stream data) : base(model, data) { } /// - public GCF(SabreTools.Models.GCF.File model, Stream data, long offset) : base(model, data, offset) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, Stream data, long offset) : base(model, data, offset) { } /// - public GCF(SabreTools.Models.GCF.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public GCF(SabreTools.Serialization.Models.GCF.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion @@ -261,7 +261,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Array of block entries /// - public SabreTools.Models.GCF.BlockEntry[]? BlockEntries; + public SabreTools.Serialization.Models.GCF.BlockEntry[]? BlockEntries; } #endregion diff --git a/SabreTools.Serialization/Wrappers/GZip.Extraction.cs b/SabreTools.Serialization/Wrappers/GZip.Extraction.cs index fec9f94c..7e90fa05 100644 --- a/SabreTools.Serialization/Wrappers/GZip.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/GZip.Extraction.cs @@ -1,8 +1,8 @@ using System; using System.IO; using SabreTools.IO.Compression.Deflate; -using SabreTools.Models.GZIP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.GZIP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/GZip.cs b/SabreTools.Serialization/Wrappers/GZip.cs index 763e4474..09f3d458 100644 --- a/SabreTools.Serialization/Wrappers/GZip.cs +++ b/SabreTools.Serialization/Wrappers/GZip.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.GZIP; +using SabreTools.Serialization.Models.GZIP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs index 2d30b574..89c845b8 100644 --- a/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.IO; -using SabreTools.Models.InstallShieldArchiveV3; +using SabreTools.Serialization.Models.InstallShieldArchiveV3; namespace SabreTools.Serialization.Wrappers { @@ -26,10 +26,10 @@ namespace SabreTools.Serialization.Wrappers public ushort FileCount => Model.Header?.FileCount ?? 0; /// - public SabreTools.Models.InstallShieldArchiveV3.Directory[] Directories => Model.Directories ?? []; + public SabreTools.Serialization.Models.InstallShieldArchiveV3.Directory[] Directories => Model.Directories ?? []; /// - public SabreTools.Models.InstallShieldArchiveV3.File[] Files => Model.Files ?? []; + public SabreTools.Serialization.Models.InstallShieldArchiveV3.File[] Files => Model.Files ?? []; /// /// Map of all files to their parent directories by index @@ -63,7 +63,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Map of all files found in the archive /// - public Dictionary FileNameMap + public Dictionary FileNameMap { get { @@ -96,7 +96,7 @@ namespace SabreTools.Serialization.Wrappers return _fileNameMap; } } - private Dictionary? _fileNameMap = null; + private Dictionary? _fileNameMap = null; /// /// Data offset for all archives diff --git a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.Extraction.cs index ca4f4847..3af5a049 100644 --- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.Extraction.cs @@ -3,9 +3,9 @@ using System.IO; using System.Text.RegularExpressions; using SabreTools.Hashing; using SabreTools.IO.Compression.zlib; -using SabreTools.Models.InstallShieldCabinet; using SabreTools.Serialization.Interfaces; -using static SabreTools.Models.InstallShieldCabinet.Constants; +using SabreTools.Serialization.Models.InstallShieldCabinet; +using static SabreTools.Serialization.Models.InstallShieldCabinet.Constants; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs index 68077534..044c1aec 100644 --- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs +++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using SabreTools.Models.InstallShieldCabinet; using SabreTools.Serialization.Extensions; +using SabreTools.Serialization.Models.InstallShieldCabinet; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/LZKWAJ.cs b/SabreTools.Serialization/Wrappers/LZKWAJ.cs index 820540bd..7e225308 100644 --- a/SabreTools.Serialization/Wrappers/LZKWAJ.cs +++ b/SabreTools.Serialization/Wrappers/LZKWAJ.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.LZ; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/LZQBasic.cs b/SabreTools.Serialization/Wrappers/LZQBasic.cs index 18aab76e..15fcd53e 100644 --- a/SabreTools.Serialization/Wrappers/LZQBasic.cs +++ b/SabreTools.Serialization/Wrappers/LZQBasic.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.LZ; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/LZSZDD.cs b/SabreTools.Serialization/Wrappers/LZSZDD.cs index c3c76e44..f9e3a78e 100644 --- a/SabreTools.Serialization/Wrappers/LZSZDD.cs +++ b/SabreTools.Serialization/Wrappers/LZSZDD.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.LZ; +using SabreTools.Serialization.Models.LZ; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs index 7eb817c0..e6a11e84 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.Extraction.cs @@ -1,8 +1,8 @@ using System; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.MicrosoftCabinet; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.MicrosoftCabinet; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index f56f9309..ccc9b7fb 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -1,7 +1,7 @@ using System; using System.IO; using SabreTools.IO.Compression.MSZIP; -using SabreTools.Models.MicrosoftCabinet; +using SabreTools.Serialization.Models.MicrosoftCabinet; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/MoPaQ.cs b/SabreTools.Serialization/Wrappers/MoPaQ.cs index fdda3019..33364373 100644 --- a/SabreTools.Serialization/Wrappers/MoPaQ.cs +++ b/SabreTools.Serialization/Wrappers/MoPaQ.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.MoPaQ; +using SabreTools.Serialization.Models.MoPaQ; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/NCF.cs b/SabreTools.Serialization/Wrappers/NCF.cs index 13404a71..ff3daf72 100644 --- a/SabreTools.Serialization/Wrappers/NCF.cs +++ b/SabreTools.Serialization/Wrappers/NCF.cs @@ -2,7 +2,7 @@ using System.IO; namespace SabreTools.Serialization.Wrappers { - public class NCF : WrapperBase + public class NCF : WrapperBase { #region Descriptive Properties @@ -14,22 +14,22 @@ namespace SabreTools.Serialization.Wrappers #region Constructors /// - public NCF(SabreTools.Models.NCF.File model, byte[] data) : base(model, data) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, byte[] data) : base(model, data) { } /// - public NCF(SabreTools.Models.NCF.File model, byte[] data, int offset) : base(model, data, offset) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public NCF(SabreTools.Models.NCF.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public NCF(SabreTools.Models.NCF.File model, Stream data) : base(model, data) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, Stream data) : base(model, data) { } /// - public NCF(SabreTools.Models.NCF.File model, Stream data, long offset) : base(model, data, offset) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, Stream data, long offset) : base(model, data, offset) { } /// - public NCF(SabreTools.Models.NCF.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public NCF(SabreTools.Serialization.Models.NCF.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion diff --git a/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs b/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs index 5ddafe59..1e369b44 100644 --- a/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs @@ -46,7 +46,7 @@ namespace SabreTools.Serialization.Wrappers int temp = overlayOffset; byte[] overlaySample = overlayData.ReadBytes(ref temp, 0x10); - if (overlaySample.StartsWith(SabreTools.Models.SevenZip.Constants.SignatureBytes)) + if (overlaySample.StartsWith(SabreTools.Serialization.Models.SevenZip.Constants.SignatureBytes)) { extension = "7z"; break; @@ -62,7 +62,7 @@ namespace SabreTools.Serialization.Wrappers extension = "7z"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.BZip2.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.BZip2.Constants.SignatureBytes)) { extension = "bz2"; break; @@ -78,37 +78,37 @@ namespace SabreTools.Serialization.Wrappers extension = "gz"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.MicrosoftCabinet.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.MicrosoftCabinet.Constants.SignatureBytes)) { extension = "cab"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) { extension = "rar"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) { extension = "rar"; break; @@ -133,7 +133,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xml"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.XZ.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.XZ.Constants.SignatureBytes)) { extension = "xz"; break; diff --git a/SabreTools.Serialization/Wrappers/PAK.cs b/SabreTools.Serialization/Wrappers/PAK.cs index bcb13180..ecef8d30 100644 --- a/SabreTools.Serialization/Wrappers/PAK.cs +++ b/SabreTools.Serialization/Wrappers/PAK.cs @@ -1,9 +1,9 @@ using System.IO; -using SabreTools.Models.PAK; +using SabreTools.Serialization.Models.PAK; namespace SabreTools.Serialization.Wrappers { - public partial class PAK : WrapperBase + public partial class PAK : WrapperBase { #region Descriptive Properties @@ -22,22 +22,22 @@ namespace SabreTools.Serialization.Wrappers #region Constructors /// - public PAK(SabreTools.Models.PAK.File model, byte[] data) : base(model, data) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, byte[] data) : base(model, data) { } /// - public PAK(SabreTools.Models.PAK.File model, byte[] data, int offset) : base(model, data, offset) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public PAK(SabreTools.Models.PAK.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public PAK(SabreTools.Models.PAK.File model, Stream data) : base(model, data) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, Stream data) : base(model, data) { } /// - public PAK(SabreTools.Models.PAK.File model, Stream data, long offset) : base(model, data, offset) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, Stream data, long offset) : base(model, data, offset) { } /// - public PAK(SabreTools.Models.PAK.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public PAK(SabreTools.Serialization.Models.PAK.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion diff --git a/SabreTools.Serialization/Wrappers/PFF.cs b/SabreTools.Serialization/Wrappers/PFF.cs index 23812772..6c42e539 100644 --- a/SabreTools.Serialization/Wrappers/PFF.cs +++ b/SabreTools.Serialization/Wrappers/PFF.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.PFF; +using SabreTools.Serialization.Models.PFF; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/PKZIP.cs b/SabreTools.Serialization/Wrappers/PKZIP.cs index 5030617b..617cab70 100644 --- a/SabreTools.Serialization/Wrappers/PKZIP.cs +++ b/SabreTools.Serialization/Wrappers/PKZIP.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.PKZIP; +using SabreTools.Serialization.Models.PKZIP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs b/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs index 7686c9d6..b5f21efc 100644 --- a/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs @@ -107,7 +107,7 @@ namespace SabreTools.Serialization.Wrappers int temp = overlayOffset; byte[] overlaySample = overlayData.ReadBytes(ref temp, 0x10); - if (overlaySample.StartsWith(SabreTools.Models.SevenZip.Constants.SignatureBytes)) + if (overlaySample.StartsWith(SabreTools.Serialization.Models.SevenZip.Constants.SignatureBytes)) { extension = "7z"; break; @@ -123,7 +123,7 @@ namespace SabreTools.Serialization.Wrappers extension = "7z"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.BZip2.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.BZip2.Constants.SignatureBytes)) { extension = "bz2"; break; @@ -139,37 +139,37 @@ namespace SabreTools.Serialization.Wrappers extension = "gz"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.MicrosoftCabinet.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.MicrosoftCabinet.Constants.SignatureBytes)) { extension = "cab"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) { extension = "zip"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) { extension = "rar"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) { extension = "rar"; break; @@ -194,7 +194,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xml"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.XZ.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.XZ.Constants.SignatureBytes)) { extension = "xz"; break; @@ -296,7 +296,7 @@ namespace SabreTools.Serialization.Wrappers int temp = resourceOffset; byte[] resourceSample = ba.ReadBytes(ref temp, 0x10); - if (resourceSample.StartsWith(SabreTools.Models.SevenZip.Constants.SignatureBytes)) + if (resourceSample.StartsWith(SabreTools.Serialization.Models.SevenZip.Constants.SignatureBytes)) { extension = "7z"; break; @@ -306,7 +306,7 @@ namespace SabreTools.Serialization.Wrappers extension = "bmp"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.BZip2.Constants.SignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.BZip2.Constants.SignatureBytes)) { extension = "bz2"; break; @@ -337,27 +337,27 @@ namespace SabreTools.Serialization.Wrappers extension = "html"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.MicrosoftCabinet.Constants.SignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.MicrosoftCabinet.Constants.SignatureBytes)) { extension = "cab"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)) { extension = "zip"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)) { extension = "zip"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.EndOfCentralDirectoryRecord64SignatureBytes)) { extension = "zip"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.PKZIP.Constants.DataDescriptorSignatureBytes)) { extension = "zip"; break; @@ -367,12 +367,12 @@ namespace SabreTools.Serialization.Wrappers extension = "png"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.RAR.Constants.OldSignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.OldSignatureBytes)) { extension = "rar"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.RAR.Constants.NewSignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.RAR.Constants.NewSignatureBytes)) { extension = "rar"; break; @@ -397,7 +397,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xml"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.XZ.Constants.SignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.XZ.Constants.SignatureBytes)) { extension = "xz"; break; diff --git a/SabreTools.Serialization/Wrappers/Quantum.cs b/SabreTools.Serialization/Wrappers/Quantum.cs index 4e6fbc7a..99a762d1 100644 --- a/SabreTools.Serialization/Wrappers/Quantum.cs +++ b/SabreTools.Serialization/Wrappers/Quantum.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.Quantum; +using SabreTools.Serialization.Models.Quantum; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/RAR.cs b/SabreTools.Serialization/Wrappers/RAR.cs index ceacd1b9..cf236461 100644 --- a/SabreTools.Serialization/Wrappers/RAR.cs +++ b/SabreTools.Serialization/Wrappers/RAR.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.RAR; +using SabreTools.Serialization.Models.RAR; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/SGA.cs b/SabreTools.Serialization/Wrappers/SGA.cs index bb31ce0d..089764cf 100644 --- a/SabreTools.Serialization/Wrappers/SGA.cs +++ b/SabreTools.Serialization/Wrappers/SGA.cs @@ -1,6 +1,6 @@ using System; using System.IO; -using SabreTools.Models.SGA; +using SabreTools.Serialization.Models.SGA; namespace SabreTools.Serialization.Wrappers { @@ -18,7 +18,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Directory data /// - public SabreTools.Models.SGA.Directory? Directory => Model.Directory; + public SabreTools.Serialization.Models.SGA.Directory? Directory => Model.Directory; /// /// Number of files in the directory @@ -164,7 +164,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Get a file header from the archive /// - public SabreTools.Models.SGA.File? GetFile(int index) + public SabreTools.Serialization.Models.SGA.File? GetFile(int index) { // If the index is invalid if (index < 0 || index >= FileCount) diff --git a/SabreTools.Serialization/Wrappers/SevenZip.cs b/SabreTools.Serialization/Wrappers/SevenZip.cs index ef01240a..90af5acf 100644 --- a/SabreTools.Serialization/Wrappers/SevenZip.cs +++ b/SabreTools.Serialization/Wrappers/SevenZip.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.SevenZip; +using SabreTools.Serialization.Models.SevenZip; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/TapeArchive.Extraction.cs b/SabreTools.Serialization/Wrappers/TapeArchive.Extraction.cs index 9ad54614..e1235d08 100644 --- a/SabreTools.Serialization/Wrappers/TapeArchive.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/TapeArchive.Extraction.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using SabreTools.Models.TAR; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.TAR; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/TapeArchive.cs b/SabreTools.Serialization/Wrappers/TapeArchive.cs index 53fa90f7..eb979a12 100644 --- a/SabreTools.Serialization/Wrappers/TapeArchive.cs +++ b/SabreTools.Serialization/Wrappers/TapeArchive.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.TAR; +using SabreTools.Serialization.Models.TAR; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/VBSP.Extraction.cs b/SabreTools.Serialization/Wrappers/VBSP.Extraction.cs index f14a7d0d..6e6a611d 100644 --- a/SabreTools.Serialization/Wrappers/VBSP.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/VBSP.Extraction.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using SabreTools.Models.BSP; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/VBSP.cs b/SabreTools.Serialization/Wrappers/VBSP.cs index 1b6cb01b..3956da44 100644 --- a/SabreTools.Serialization/Wrappers/VBSP.cs +++ b/SabreTools.Serialization/Wrappers/VBSP.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.BSP; +using SabreTools.Serialization.Models.BSP; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/VPK.Extraction.cs b/SabreTools.Serialization/Wrappers/VPK.Extraction.cs index 8784718f..3e9bc406 100644 --- a/SabreTools.Serialization/Wrappers/VPK.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/VPK.Extraction.cs @@ -2,7 +2,7 @@ using System; using System.IO; using SabreTools.IO.Extensions; using SabreTools.Serialization.Interfaces; -using static SabreTools.Models.VPK.Constants; +using static SabreTools.Serialization.Models.VPK.Constants; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/VPK.cs b/SabreTools.Serialization/Wrappers/VPK.cs index 6b9c136e..b83aceaa 100644 --- a/SabreTools.Serialization/Wrappers/VPK.cs +++ b/SabreTools.Serialization/Wrappers/VPK.cs @@ -1,10 +1,10 @@ using System; using System.IO; -using static SabreTools.Models.VPK.Constants; +using static SabreTools.Serialization.Models.VPK.Constants; namespace SabreTools.Serialization.Wrappers { - public partial class VPK : WrapperBase + public partial class VPK : WrapperBase { #region Descriptive Properties @@ -71,7 +71,7 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.VPK.DirectoryItem[]? DirectoryItems => Model.DirectoryItems; + public SabreTools.Serialization.Models.VPK.DirectoryItem[]? DirectoryItems => Model.DirectoryItems; #endregion @@ -87,22 +87,22 @@ namespace SabreTools.Serialization.Wrappers #region Constructors /// - public VPK(SabreTools.Models.VPK.File model, byte[] data) : base(model, data) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, byte[] data) : base(model, data) { } /// - public VPK(SabreTools.Models.VPK.File model, byte[] data, int offset) : base(model, data, offset) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public VPK(SabreTools.Models.VPK.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public VPK(SabreTools.Models.VPK.File model, Stream data) : base(model, data) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, Stream data) : base(model, data) { } /// - public VPK(SabreTools.Models.VPK.File model, Stream data, long offset) : base(model, data, offset) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, Stream data, long offset) : base(model, data, offset) { } /// - public VPK(SabreTools.Models.VPK.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public VPK(SabreTools.Serialization.Models.VPK.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion diff --git a/SabreTools.Serialization/Wrappers/WAD3.cs b/SabreTools.Serialization/Wrappers/WAD3.cs index 39417bab..b301eba1 100644 --- a/SabreTools.Serialization/Wrappers/WAD3.cs +++ b/SabreTools.Serialization/Wrappers/WAD3.cs @@ -2,7 +2,7 @@ using System.IO; namespace SabreTools.Serialization.Wrappers { - public partial class WAD3 : WrapperBase + public partial class WAD3 : WrapperBase { #region Descriptive Properties @@ -14,29 +14,29 @@ namespace SabreTools.Serialization.Wrappers #region Extension Properties /// - public SabreTools.Models.WAD3.DirEntry[]? DirEntries => Model.DirEntries; + public SabreTools.Serialization.Models.WAD3.DirEntry[]? DirEntries => Model.DirEntries; #endregion #region Constructors /// - public WAD3(SabreTools.Models.WAD3.File model, byte[] data) : base(model, data) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, byte[] data) : base(model, data) { } /// - public WAD3(SabreTools.Models.WAD3.File model, byte[] data, int offset) : base(model, data, offset) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public WAD3(SabreTools.Models.WAD3.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public WAD3(SabreTools.Models.WAD3.File model, Stream data) : base(model, data) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, Stream data) : base(model, data) { } /// - public WAD3(SabreTools.Models.WAD3.File model, Stream data, long offset) : base(model, data, offset) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, Stream data, long offset) : base(model, data, offset) { } /// - public WAD3(SabreTools.Models.WAD3.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public WAD3(SabreTools.Serialization.Models.WAD3.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion diff --git a/SabreTools.Serialization/Wrappers/XZ.cs b/SabreTools.Serialization/Wrappers/XZ.cs index 8bc52341..23bf6c66 100644 --- a/SabreTools.Serialization/Wrappers/XZ.cs +++ b/SabreTools.Serialization/Wrappers/XZ.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.XZ; +using SabreTools.Serialization.Models.XZ; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/XZP.cs b/SabreTools.Serialization/Wrappers/XZP.cs index e187db27..1e82bc3e 100644 --- a/SabreTools.Serialization/Wrappers/XZP.cs +++ b/SabreTools.Serialization/Wrappers/XZP.cs @@ -2,7 +2,7 @@ using System.IO; namespace SabreTools.Serialization.Wrappers { - public partial class XZP : WrapperBase + public partial class XZP : WrapperBase { #region Descriptive Properties @@ -14,32 +14,32 @@ namespace SabreTools.Serialization.Wrappers #region Extension Properties /// - public SabreTools.Models.XZP.DirectoryEntry[]? DirectoryEntries => Model.DirectoryEntries; + public SabreTools.Serialization.Models.XZP.DirectoryEntry[]? DirectoryEntries => Model.DirectoryEntries; /// - public SabreTools.Models.XZP.DirectoryItem[]? DirectoryItems => Model.DirectoryItems; + public SabreTools.Serialization.Models.XZP.DirectoryItem[]? DirectoryItems => Model.DirectoryItems; #endregion #region Constructors /// - public XZP(SabreTools.Models.XZP.File model, byte[] data) : base(model, data) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, byte[] data) : base(model, data) { } /// - public XZP(SabreTools.Models.XZP.File model, byte[] data, int offset) : base(model, data, offset) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, byte[] data, int offset) : base(model, data, offset) { } /// - public XZP(SabreTools.Models.XZP.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, byte[] data, int offset, int length) : base(model, data, offset, length) { } /// - public XZP(SabreTools.Models.XZP.File model, Stream data) : base(model, data) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, Stream data) : base(model, data) { } /// - public XZP(SabreTools.Models.XZP.File model, Stream data, long offset) : base(model, data, offset) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, Stream data, long offset) : base(model, data, offset) { } /// - public XZP(SabreTools.Models.XZP.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } + public XZP(SabreTools.Serialization.Models.XZP.File model, Stream data, long offset, long length) : base(model, data, offset, length) { } #endregion