// Noddybox.DOOM - DOOM WAD Wrapper // Copyright (C) 2004 Ian Cowburn // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // using System; using System.IO; using System.Collections; using System.Text; namespace Noddybox.DOOM { /// /// Defines a WAD File /// public class WAD : IEnumerable, IEnumerator { // ==================================== // PUBLIC // ==================================== /// /// Describes the type of WAD /// public enum EWadType { /// /// An Interal WAD (eg. DOOM 2) /// IWAD, /// /// A Patch WAD (eg. a user-defined level) /// PWAD }; /// /// Construct a new, empty WAD file /// public WAD() { m_type=EWadType.PWAD; m_entry=new ArrayList(); m_ascii=new ASCIIEncoding(); } /// /// Load a WAD file from disk /// /// The WAD file /// /// I/O errors /// public WAD(string path) { m_path=path; m_entry=new ArrayList(); m_ascii=new ASCIIEncoding(); Load(); } /// /// Get/set the path of the WAD file on disk /// public string Path { get {return m_path;} set {m_path=value;} } /// /// Get the type of WAD file /// public EWadType WadType { get {return m_type;} } /// /// Adds a new lump to the WAD /// /// The lump public void AddEntry(WADEntry e) { m_entry.Add(e); } /// /// Removes a lump from the WAD /// /// The lump public void RemoveEntry(WADEntry e) { m_entry.Remove(e); } /// /// Find a lump /// /// The name to find /// The first lump that matches the name, or null for no match public WADEntry FindEntry(string name) { foreach (WADEntry e in m_entry) { if (e.Name==name) { return e; } } return null; } /// /// Load a WAD file /// /// /// I/O errors /// public void Load() { if (m_path==null) { throw new DoomException("Tried to load a WAD without a path"); } FileStream fs=File.OpenRead(m_path); string id=ReadString(fs,4); if (id=="IWAD") { m_type=EWadType.IWAD; } else if (id=="PWAD") { m_type=EWadType.PWAD; } else { fs.Close(); throw new DoomException("Not a WAD File - " + m_path); } m_entry.Clear(); int num=ReadLong(fs); if (num>0) { fs.Position=ReadLong(fs); for(int f=0;f /// Saves the WAD file /// /// /// Tried to save an IWAD file /// /// /// I/O errors /// public void Save() { if (m_path==null) { throw new DoomException("Tried to save a WAD without a path"); } if (m_type==EWadType.IWAD) { throw new DoomException("Tried to save an IWAD"); } FileStream fs=File.Create(m_path); int len=0; foreach (WADEntry e in this) { len+=e.Length; } WriteString(fs,"PWAD",4); WriteLong(fs,m_entry.Count); int offset=12; WriteLong(fs,len+offset); foreach (WADEntry e in m_entry) { fs.Write(e.Data,0,e.Length); } foreach (WADEntry e in m_entry) { WriteLong(fs,offset); WriteLong(fs,e.Length); WriteString(fs,e.Name,8); offset+=e.Length; } fs.Close(); } /// /// Returns the number of lumps in the WAD /// public int Count { get {return m_entry.Count;} } /// /// Index into the lumps /// public WADEntry this[int index] { get {return (WADEntry)m_entry[index];} } /// /// Gets an enumerator /// /// The enumerator public IEnumerator GetEnumerator() { Reset(); return this; } /// /// Get the current object from the enumerator /// public object Current { get { if (m_iter_index==-1) { throw new InvalidOperationException(); } return m_entry[m_iter_index]; } } /// /// Reset the enumerator to the start of the collection. /// public void Reset() { m_iter_index=-1; } /// /// Move the enumerator to the next item. /// /// True if there are more objects to enumerate over public bool MoveNext() { m_iter_index++; if (m_iter_index>=m_entry.Count) { m_iter_index=-1; } return m_iter_index!=-1; } // ==================================== // PRIVATE // ==================================== private string m_path; private EWadType m_type; private ArrayList m_entry; private ASCIIEncoding m_ascii; private int m_iter_index; private int ReadLong(FileStream fs) { int l=0; for(int f=0;f<4;f++) { int b=fs.ReadByte(); l|=b<<(f*8); } return l; } private string ReadString(FileStream fs, int len) { byte[] data=new byte[len]; fs.Read(data,0,len); return m_ascii.GetString(data,0,len); } private void WriteLong(FileStream fs, int l) { for(int f=0;f<4;f++) { fs.WriteByte((byte)(l&0xff)); l=l>>8; } } private void WriteString(FileStream fs, string s, int len) { byte[] data=m_ascii.GetBytes(s); for(int f=0;f