summaryrefslogtreecommitdiff
path: root/WAD.cs
diff options
context:
space:
mode:
Diffstat (limited to 'WAD.cs')
-rw-r--r--WAD.cs365
1 files changed, 365 insertions, 0 deletions
diff --git a/WAD.cs b/WAD.cs
new file mode 100644
index 0000000..42a687d
--- /dev/null
+++ b/WAD.cs
@@ -0,0 +1,365 @@
+// 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
+{
+ /// <summary>
+ /// Defines a WAD File
+ /// </summary>
+ public class WAD : IEnumerable, IEnumerator
+ {
+ // ====================================
+ // PUBLIC
+ // ====================================
+
+ /// <summary>
+ /// Describes the type of WAD
+ /// </summary>
+ public enum EWadType
+ {
+ /// <summary>
+ /// An Interal WAD (eg. DOOM 2)
+ /// </summary>
+ IWAD,
+
+ /// <summary>
+ /// A Patch WAD (eg. a user-defined level)
+ /// </summary>
+ PWAD
+ };
+
+ /// <summary>
+ /// Construct a new, empty WAD file
+ /// </summary>
+ public WAD()
+ {
+ m_type=EWadType.PWAD;
+ m_entry=new ArrayList();
+ m_ascii=new ASCIIEncoding();
+ }
+
+ /// <summary>
+ /// Load a WAD file from disk
+ /// </summary>
+ /// <param name="path">The WAD file</param>
+ /// <exception cref="System.IO.IOException">
+ /// I/O errors
+ /// </exception>
+ public WAD(string path)
+ {
+ m_path=path;
+ m_entry=new ArrayList();
+ m_ascii=new ASCIIEncoding();
+ Load();
+ }
+
+ /// <summary>
+ /// Get/set the path of the WAD file on disk
+ /// </summary>
+ public string Path
+ {
+ get {return m_path;}
+ set {m_path=value;}
+ }
+
+ /// <summary>
+ /// Get the type of WAD file
+ /// </summary>
+ public EWadType WadType
+ {
+ get {return m_type;}
+ }
+
+ /// <summary>
+ /// Adds a new lump to the WAD
+ /// </summary>
+ /// <param name="e">The lump</param>
+ public void AddEntry(WADEntry e)
+ {
+ m_entry.Add(e);
+ }
+
+ /// <summary>
+ /// Removes a lump from the WAD
+ /// </summary>
+ /// <param name="e">The lump</param>
+ public void RemoveEntry(WADEntry e)
+ {
+ m_entry.Remove(e);
+ }
+
+ /// <summary>
+ /// Find a lump
+ /// </summary>
+ /// <param name="name">The name to find</param>
+ /// <returns>The first lump that matches the name, or null for no match</returns>
+ public WADEntry FindEntry(string name)
+ {
+ foreach (WADEntry e in m_entry)
+ {
+ if (e.Name==name)
+ {
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Load a WAD file
+ /// </summary>
+ /// <exception cref="System.IO.IOException">
+ /// I/O errors
+ /// </exception>
+ 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<num;f++)
+ {
+ int off=ReadLong(fs);
+ int len=ReadLong(fs);
+ string name=ReadString(fs,8);
+
+ long cur=fs.Position;
+
+ byte[] data=new byte[len];
+
+ fs.Position=off;
+ fs.Read(data,0,len);
+ fs.Position=cur;
+
+ m_entry.Add(new WADEntry(name,data));
+ }
+ }
+
+ fs.Close();
+ }
+
+ /// <summary>
+ /// Saves the WAD file
+ /// </summary>
+ /// <exception cref="Noddybox.DOOM.DoomException">
+ /// Tried to save an IWAD file
+ /// </exception>
+ /// <exception cref="System.IO.IOException">
+ /// I/O errors
+ /// </exception>
+ 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();
+ }
+
+ /// <summary>
+ /// Returns the number of lumps in the WAD
+ /// </summary>
+ public int Count
+ {
+ get {return m_entry.Count;}
+ }
+
+ /// <summary>
+ /// Index into the lumps
+ /// </summary>
+ public WADEntry this[int index]
+ {
+ get {return (WADEntry)m_entry[index];}
+ }
+
+ /// <summary>
+ /// Gets an enumerator
+ /// </summary>
+ /// <returns>The enumerator</returns>
+ public IEnumerator GetEnumerator()
+ {
+ Reset();
+ return this;
+ }
+
+ /// <summary>
+ /// Get the current object from the enumerator
+ /// </summary>
+ public object Current
+ {
+ get
+ {
+ if (m_iter_index==-1)
+ {
+ throw new InvalidOperationException();
+ }
+
+ return m_entry[m_iter_index];
+ }
+ }
+
+ /// <summary>
+ /// Reset the enumerator to the start of the collection.
+ /// </summary>
+ public void Reset()
+ {
+ m_iter_index=-1;
+ }
+
+ /// <summary>
+ /// Move the enumerator to the next item.
+ /// </summary>
+ /// <returns>True if there are more objects to enumerate over</returns>
+ 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<len;f++)
+ {
+ if (f<data.Length)
+ {
+ fs.WriteByte(data[f]);
+ }
+ else
+ {
+ fs.WriteByte(0);
+ }
+ }
+ }
+ }
+}