예제 #1
0
        /// <summary>
        /// Updates the lump data offsets in the lump headers. Must be called when any lump's data size has changed.
        /// </summary>
        private void UpdateLumpDataOffsets()
        {
            var pos = VBSPHeaderSize;

            foreach (var lump in Lumps.OrderBy(lump => lump.DataOrder))
            {
                // Notify the lump about us updating the offsets.
                // This is necessary for the GameLump which for some dumb reason has absolute file offsets and not local offsets
                lump.UpdateOffsets(pos);

                lump.Offset = pos;
                pos         = Util.RoundUp(pos + lump.Data.Length, 4); // Lumps should appear on int boundaries in the BSP file
            }
        }
예제 #2
0
        /// <summary>
        /// Writes the BSP header and lump data using a BinaryWriter stream
        /// </summary>
        /// <param name="writer">The BinaryWriter stream</param>
        public void WriteBSP(BinaryWriter writer)
        {
            UpdateLumpDataOffsets();

            // Write header
            writer.Write(VBSP);
            writer.Write(Version);
            foreach (var lump in Lumps)
            {
                lump.WriteHeader(writer);
            }
            writer.Write(Revision);

            // Write lump contents
            foreach (var lump in Lumps.OrderBy(lump => lump.Offset))
            {
                writer.Seek(lump.Offset, SeekOrigin.Begin);
                lump.WriteData(writer);
            }
        }
예제 #3
0
 public static int GetLump(Lumps lump) => (int)lump;
 public DirectoryEntry GetLump(Lumps lump)
 {
     return(directory[(int)lump]);
 }
예제 #5
0
        private void Read(BinaryReader br)
        {
            Header = new Header
            {
                Version    = (Version)br.ReadUInt32(),
                NumLumps   = br.ReadInt32(),
                LumpOffest = br.ReadInt32()
            };

            if (Header.Version != Version.Wad2 && Header.Version != Version.Wad3)
            {
                throw new NotSupportedException("Only Goldsource (WAD2 & WAD3) WAD files are supported.");
            }

            br.BaseStream.Seek(Header.LumpOffest, SeekOrigin.Begin);
            for (var i = 0; i < Header.NumLumps; i++)
            {
                var lump = new Lump
                {
                    Offset           = br.ReadInt32(),
                    CompressedSize   = br.ReadInt32(),
                    UncompressedSize = br.ReadInt32(),
                    Type             = (LumpType)br.ReadByte(),
                    Compression      = br.ReadByte()
                };
                br.ReadBytes(2);
                var name = br.ReadChars(Lump.NameLength);
                var len  = Array.IndexOf(name, '\0');
                lump.Name = new string(name, 0, len < 0 ? name.Length : len);
                Lumps.Add(lump);
            }

            foreach (var lump in Lumps)
            {
                br.BaseStream.Seek(lump.Offset, SeekOrigin.Begin);
                Texture texture;
                switch (lump.Type)
                {
                case LumpType.Image:
                    texture = new Texture
                    {
                        Name    = lump.Name,
                        Width   = br.ReadUInt32(),
                        Height  = br.ReadUInt32(),
                        NumMips = 1
                    };
                    var size = (int)(texture.Width * texture.Height);
                    texture.MipData = new[] { br.ReadBytes(size) };
                    var paletteSize = br.ReadUInt16();
                    texture.Palette = br.ReadBytes(paletteSize * 3);
                    break;

                case LumpType.Texture:
                    texture = ReadMipTexture(br);
                    break;

                default:
                    continue;
                }

                Textures[texture.Name] = texture;
            }
        }
예제 #6
0
        /// <summary>
        /// Reads the data of a HOG file from a stream.
        /// </summary>
        /// <param name="stream">The stream to read the HOG file from. The stream must be seekable</param>
        public void Read(Stream stream)
        {
            lock (hogFileLock)
            {
                if (!stream.CanSeek)
                {
                    throw new ArgumentException("HOGFIle:Read: Passed stream must be seekable.");
                }

                BinaryReader br = new BinaryReader(stream);
                fileStream = br;
                Lumps.Clear();

                char[] header = new char[3];
                header[0] = (char)br.ReadByte();
                header[1] = (char)br.ReadByte();
                header[2] = (char)br.ReadByte();

                var headerString = new string(header);
                switch (headerString)
                {
                case "DHF":
                    Format = HOGFormat.Standard;
                    break;

                case "D2X":
                    Format = HOGFormat.D2X_XL;
                    break;

                default:
                    throw new InvalidDataException($"Unrecognized HOG header \"{headerString}\"");
                }

                try
                {
                    while (true)
                    {
                        char[] filenamedata = new char[13];
                        bool   hashitnull   = false;
                        for (int x = 0; x < 13; x++)
                        {
                            char c = (char)br.ReadByte();
                            if (c == 0)
                            {
                                hashitnull = true;
                            }
                            if (!hashitnull)
                            {
                                filenamedata[x] = c;
                            }
                        }
                        string filename = new string(filenamedata);
                        filename = filename.Trim(' ', '\0');
                        int filesize = br.ReadInt32();
                        if (Format == HOGFormat.D2X_XL && filesize < 0)
                        {
                            // D2X-XL format encodes "extended" lump headers with negative file sizes
                            filesize = -filesize;

                            string longFilename = Encoding.ASCII.GetString(br.ReadBytes(256));
                            if (longFilename.Contains("\0"))
                            {
                                longFilename = longFilename.Remove(longFilename.IndexOf('\0'));
                            }
                            longFilename = longFilename.Trim(' ');
                            // No real reason to use short filename in this instance; just replace it
                            filename = longFilename;
                        }
                        int offset = (int)br.BaseStream.Position;
                        br.BaseStream.Seek(filesize, SeekOrigin.Current); //I hate hog files. Wads are cooler..

                        HOGLump lump = new HOGLump(filename, filesize, offset);
                        Lumps.Add(lump);
                    }
                }
                catch (EndOfStreamException)
                {
                    //we got all the files
                    //heh
                    //i love hog
                    //classification now lives in EditorHOGFile since only editors care about it
                }
            }
        }