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; }
+ }
+}