4 using System
.Collections
.Generic
;
15 public short DataVersion
;
16 public string Filename
;
17 public uint Checksum
{
27 return Directory
.Count
;
31 short applicationSpecificDirectoryDataSize
;
32 short entryHeaderSize
;
33 short directoryEntryBaseSize
;
34 public uint ParentChecksum
;
36 public class BadMapException
: Exception
{
37 public BadMapException()
41 public BadMapException(string message
) : base(message
)
45 public BadMapException(string message
, Exception inner
) : base(message
, inner
)
50 public class DirectoryEntry
{
51 public short MissionFlags
;
52 public short EnvironmentFlags
;
53 public int EntryPointFlags
;
54 public string LevelName
;
55 public Dictionary
<uint, byte[]> Chunks
= new Dictionary
<uint, byte[]> ();
57 internal const int DataSize
= 74;
62 internal void LoadEntry(BinaryReaderBE reader
) {
63 Offset
= reader
.ReadInt32();
64 Size
= reader
.ReadInt32();
65 Index
= reader
.ReadInt16();
68 internal void LoadData(BinaryReaderBE reader
) {
69 MissionFlags
= reader
.ReadInt16();
70 EnvironmentFlags
= reader
.ReadInt16();
71 EntryPointFlags
= reader
.ReadInt32();
72 const int kLevelNameLength
= 66;
73 LevelName
= reader
.ReadMacString(kLevelNameLength
);
76 internal void LoadChunks(BinaryReaderBE reader
) {
77 long position
= reader
.BaseStream
.Position
;
80 uint tag
= reader
.ReadUInt32();
81 nextOffset
= reader
.ReadInt32();
82 int length
= reader
.ReadInt32();
83 reader
.ReadInt32(); // offset
85 Chunks
[tag
] = reader
.ReadBytes(length
);
88 reader
.BaseStream
.Seek(position
+ nextOffset
, SeekOrigin
.Begin
);
89 } while (nextOffset
> 0);
93 public SortedDictionary
<int, DirectoryEntry
> Directory
= new SortedDictionary
<int, DirectoryEntry
> ();
95 public void Load(string filename
) {
96 BinaryReaderBE reader
= new BinaryReaderBE(File
.Open(filename
, FileMode
.Open
));
99 version
= reader
.ReadInt16();
100 DataVersion
= reader
.ReadInt16();
101 Filename
= reader
.ReadMacString(64);
102 checksum
= reader
.ReadUInt32();
103 directoryOffset
= reader
.ReadInt32();
104 short wadCount
= reader
.ReadInt16();
105 applicationSpecificDirectoryDataSize
= reader
.ReadInt16();
106 entryHeaderSize
= reader
.ReadInt16();
108 directoryEntryBaseSize
= reader
.ReadInt16();
110 // sanity check the map
111 if (Version
< 2 || DataVersion
< 1 || entryHeaderSize
!= 16 || directoryEntryBaseSize
!= 10) {
112 throw new BadMapException("Only Marathon 2 and higher maps are supported");
115 ParentChecksum
= reader
.ReadUInt32();
116 reader
.ReadBytes(2 * 20); // unused
118 // load the directory
119 reader
.BaseStream
.Seek(directoryOffset
, SeekOrigin
.Begin
);
120 for (int i
= 0; i
< wadCount
; ++i
) {
121 DirectoryEntry entry
= new DirectoryEntry();
122 entry
.LoadEntry(reader
);
124 if (applicationSpecificDirectoryDataSize
== DirectoryEntry
.DataSize
) {
125 entry
.LoadData(reader
);
127 reader
.ReadBytes(applicationSpecificDirectoryDataSize
);
129 Directory
[entry
.Index
] = entry
;
132 // load all the wads(!)
133 foreach (KeyValuePair
<int, DirectoryEntry
> kvp
in Directory
) {
134 reader
.BaseStream
.Seek(kvp
.Value
.Offset
, SeekOrigin
.Begin
);
135 kvp
.Value
.LoadChunks(reader
);
142 static public void Main(string[] args
) {
143 if (args
.Length
== 1) {
144 Wadfile wadfile
= new Wadfile();
145 wadfile
.Load(args
[0]);
146 Console
.WriteLine("{0}: 0x{1:x}", wadfile
.Filename
, wadfile
.Checksum
);
147 foreach (KeyValuePair
<int, DirectoryEntry
> kvp
in wadfile
.Directory
) {
148 Console
.WriteLine("{0}\t{1}\t{2}", kvp
.Key
, kvp
.Value
.Chunks
.Count
, kvp
.Value
.LevelName
);
151 Console
.WriteLine("Test usage: wadfile.exe <wadfile>");