add MapWindow.cs; don't show resources in levels menu
[weland.git] / Wadfile.cs
blob0f6eca3f61a67247286eef3b64c4578643a78734
1 using System;
2 using System.Text;
3 using System.IO;
4 using System.Collections.Generic;
6 namespace Weland {
7 public class Wadfile {
8 public short Version {
9 get {
10 return version;
13 short version;
15 public short DataVersion;
16 public string Filename;
17 public uint Checksum {
18 get {
19 return checksum;
22 uint checksum;
24 int directoryOffset;
25 public int WadCount {
26 get {
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;
58 internal int Offset;
59 internal int Size;
60 internal short Index;
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;
78 int nextOffset;
79 do {
80 uint tag = reader.ReadUInt32();
81 nextOffset = reader.ReadInt32();
82 int length = reader.ReadInt32();
83 reader.ReadInt32(); // offset
85 Chunks[tag] = reader.ReadBytes(length);
87 if (nextOffset > 0)
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));
97 try {
98 // read the header
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);
126 } else {
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);
137 } finally {
138 reader.Close();
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);
150 } else {
151 Console.WriteLine("Test usage: wadfile.exe <wadfile>");