diff --git a/SabreTools.Models/WAD/Lump.cs b/SabreTools.Models/WAD/Lump.cs deleted file mode 100644 index 5ba8aa5..0000000 --- a/SabreTools.Models/WAD/Lump.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Runtime.InteropServices; - -namespace SabreTools.Models.WAD -{ - /// - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public sealed class Lump - { - public uint Offset; - - public uint DiskLength; - - public uint Length; - - public byte Type; - - public byte Compression; - - public byte Padding0; - - public byte Padding1; - - /// 16 bytes - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] - public string? Name; - } -} diff --git a/SabreTools.Models/WAD/LumpInfo.cs b/SabreTools.Models/WAD/LumpInfo.cs deleted file mode 100644 index c6e9646..0000000 --- a/SabreTools.Models/WAD/LumpInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Runtime.InteropServices; - -namespace SabreTools.Models.WAD -{ - /// - public sealed class LumpInfo - { - /// - /// Type 0x42 has no name, type 0x43 does - /// - /// 16 bytes - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] - public string? Name; - - public uint Width; - - public uint Height; - - public uint PixelOffset; - - /// - /// Unknown data - /// - /// 12 bytes - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] - public byte[]? UnknownData; - - /// Width * Height bytes located at PixelOffset - public byte[]? PixelData { get; set; } - - // TODO: Determine what mipmap data looks like - - public uint PaletteSize { get; set; } - - /// PaletteSize * 3 bytes - public byte[]? PaletteData { get; set; } - } -} diff --git a/SabreTools.Models/WAD3/CharInfo.cs b/SabreTools.Models/WAD3/CharInfo.cs new file mode 100644 index 0000000..335c321 --- /dev/null +++ b/SabreTools.Models/WAD3/CharInfo.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Models.WAD3 +{ + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class CharInfo + { + public ushort StartOffset; + + public ushort CharWidth; + } +} diff --git a/SabreTools.Models/WAD/Constants.cs b/SabreTools.Models/WAD3/Constants.cs similarity index 88% rename from SabreTools.Models/WAD/Constants.cs rename to SabreTools.Models/WAD3/Constants.cs index 16e1f8f..5007a8d 100644 --- a/SabreTools.Models/WAD/Constants.cs +++ b/SabreTools.Models/WAD3/Constants.cs @@ -1,4 +1,4 @@ -namespace SabreTools.Models.WAD +namespace SabreTools.Models.WAD3 { public static class Constants { diff --git a/SabreTools.Models/WAD3/DirEntry.cs b/SabreTools.Models/WAD3/DirEntry.cs new file mode 100644 index 0000000..fba2385 --- /dev/null +++ b/SabreTools.Models/WAD3/DirEntry.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.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.Models/WAD3/Enums.cs b/SabreTools.Models/WAD3/Enums.cs new file mode 100644 index 0000000..f1dfdd8 --- /dev/null +++ b/SabreTools.Models/WAD3/Enums.cs @@ -0,0 +1,28 @@ +namespace SabreTools.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.Models/WAD/File.cs b/SabreTools.Models/WAD3/File.cs similarity index 65% rename from SabreTools.Models/WAD/File.cs rename to SabreTools.Models/WAD3/File.cs index c21f361..cd1923d 100644 --- a/SabreTools.Models/WAD/File.cs +++ b/SabreTools.Models/WAD3/File.cs @@ -1,4 +1,4 @@ -namespace SabreTools.Models.WAD +namespace SabreTools.Models.WAD3 { /// /// Half-Life Texture Package File @@ -12,13 +12,13 @@ namespace SabreTools.Models.WAD public Header? Header { get; set; } /// - /// Deserialized lumps data + /// Deserialized dir entry data /// - public Lump?[]? Lumps { get; set; } + public DirEntry?[]? DirEntries { get; set; } /// - /// Deserialized lump infos data + /// Deserialized file entry data /// - public LumpInfo?[]? LumpInfos { get; set; } + public FileEntry?[]? FileEntries { get; set; } } } diff --git a/SabreTools.Models/WAD3/FileEntry.cs b/SabreTools.Models/WAD3/FileEntry.cs new file mode 100644 index 0000000..eb6f20f --- /dev/null +++ b/SabreTools.Models/WAD3/FileEntry.cs @@ -0,0 +1,11 @@ +namespace SabreTools.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.Models/WAD3/Font.cs b/SabreTools.Models/WAD3/Font.cs new file mode 100644 index 0000000..545777e --- /dev/null +++ b/SabreTools.Models/WAD3/Font.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.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.Models/WAD/Header.cs b/SabreTools.Models/WAD3/Header.cs similarity index 65% rename from SabreTools.Models/WAD/Header.cs rename to SabreTools.Models/WAD3/Header.cs index e49a7e8..c45d3f6 100644 --- a/SabreTools.Models/WAD/Header.cs +++ b/SabreTools.Models/WAD3/Header.cs @@ -1,8 +1,9 @@ using System.Runtime.InteropServices; -namespace SabreTools.Models.WAD +namespace SabreTools.Models.WAD3 { /// + /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public sealed class Header { @@ -14,13 +15,13 @@ namespace SabreTools.Models.WAD public string? Signature; /// - /// Number of lumps in the file + /// Number of Directory entries /// - public uint LumpCount; + public uint NumDirs; /// - /// Offset where lumps are stored + /// Offset from the WAD3 data's beginning for first Directory entry /// - public uint LumpOffset; + public uint DirOffset; } } diff --git a/SabreTools.Models/WAD3/MipMap.cs b/SabreTools.Models/WAD3/MipMap.cs new file mode 100644 index 0000000..f118c05 --- /dev/null +++ b/SabreTools.Models/WAD3/MipMap.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.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.Models/WAD3/MipTex.cs b/SabreTools.Models/WAD3/MipTex.cs new file mode 100644 index 0000000..d4ec2be --- /dev/null +++ b/SabreTools.Models/WAD3/MipTex.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.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.Models/WAD3/QpicImage.cs b/SabreTools.Models/WAD3/QpicImage.cs new file mode 100644 index 0000000..efe89b4 --- /dev/null +++ b/SabreTools.Models/WAD3/QpicImage.cs @@ -0,0 +1,33 @@ +namespace SabreTools.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; } + } +}