public static void Load(WadFile wad, Stream stream) { if (wad == null) { throw new ArgumentNullException("wad"); } if (stream == null) { throw new ArgumentOutOfRangeException("stream"); } var reader = new BinaryReader(stream); var startOffset = stream.Position;// Position of start in stream (current - version) // Validate version uint version = reader.ReadUInt32(); if (version != Version) { throw new BspLib.Wad.Exceptions.WadVersionNotSupportedException(version); } // Header int num = reader.ReadInt32(); // Number of entries, not textures int offset = reader.ReadInt32(); var entries = new List <WadEntry>(); // Offset of entries // Often bedore end of file stream.Position = offset + startOffset; for (int i = 0; i < num; i++) { var entry = WadEntry.Read(reader); // Is a texture if (entry.Type == WadEntry.TextureType) { // Compressed if (entry.Compressed) { // Could not find how it works (no documentation). // In official github ( https://github.com/ValveSoftware/halflife/blob/5d761709a31ce1e71488f2668321de05f791b405/utils/common/wadlib.c on line 301 ): // // F I X M E: do compression Console.Error.WriteLine("WadEntry ID={0}, Name='{1}' is compressed texture which is not supported. Skipping.", i, entry.Name_s); } // Not Compressed else { entries.Add(entry); } } // Not a texture else { Console.Error.WriteLine("WadEntry ID={0}, Name='{1}' has unknown / unsupported type 0x{2:X2}.", i, entry.Name_s, entry.Type); } } // Load all textures for (int i = 0; i < entries.Count; i++) { var entry = entries[i]; stream.Position = entry.PositionInFile + startOffset; var texture_info = TextureLumpInfo.Load(reader); var texture = texture_info.LoadTexture(reader, entry.PositionInFile); wad.Textures.Add(texture); } }
public static void Save(WadFile wad, Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } var writer = new BinaryWriter(stream); var startOffset = stream.Position; // Version writer.Write(Version); writer.Flush(); // Header // Valid texture count (number of entries) writer.Write((int)wad.Textures.Count(t => t is Texture)); // TextureLumpInfo offset position // Will be changed later var global_textureLumpInfo_offset_position = stream.Position; writer.Write((int)0); writer.Flush(); List <int> positions = new List <int>(); List <char[]> names = new List <char[]>(); List <int> sizes = new List <int>(); for (int i = 0; i < wad.Textures.Count; i++) { long position = stream.Position - startOffset; positions.Add((int)position); TextureByteIndexPaletteWithMipmaps texture; TextureLumpInfo textureLump; var t = wad.Textures[i]; if (t is TextureByteIndexPalette) { if (t is TextureByteIndexPaletteWithMipmaps) { texture = (TextureByteIndexPaletteWithMipmaps)t; } else { var tbip = (TextureByteIndexPalette)t; texture = tbip.GenerateMipmaps(TextureLumpInfo.MipmapOffsetsLength); } } else { //throw new NotImplementedException("Textures without byte palette are not supported yet"); var tbip = TextureByteIndexPalette.CreateFromBitmap(t); texture = tbip.GenerateMipmaps(TextureLumpInfo.MipmapOffsetsLength); } textureLump = new TextureLumpInfo(texture); textureLump.Save(writer); long length = stream.Position - position - startOffset; sizes.Add((int)length); } var global_wadEntry_position = stream.Position; stream.Position = global_textureLumpInfo_offset_position; writer.Write((int)(global_wadEntry_position - startOffset)); writer.Flush(); stream.Position = global_wadEntry_position; for (int i = 0; i < positions.Count; i++) { var position = positions[i]; var name = names[i]; var size = sizes[i]; var entry = new WadEntry((int)(position - startOffset), size, WadEntry.TextureType, name); entry.Write(writer); } }