diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADDataFormat.cs
new file mode 100644
index 00000000..f084b6f0
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADDataFormat.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UniversalEditor.IO;
+using UniversalEditor.ObjectModels.FileSystem;
+
+namespace UniversalEditor.DataFormats.FileSystem.GremlinInteractive.ActuaSoccer.MAD
+{
+ public class MADDataFormat : DataFormat
+ {
+ private static DataFormatReference _dfr = null;
+ public override DataFormatReference MakeReference()
+ {
+ if (_dfr == null)
+ {
+ _dfr = base.MakeReference();
+ _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
+ _dfr.ExportOptions.Add(new CustomOptionChoice("FormatVersion", "Format &version:", true, new CustomOptionFieldChoice[]
+ {
+ new CustomOptionFieldChoice("Type 1 (includes file names)", MADFormatVersion.Type1, true),
+ new CustomOptionFieldChoice("Type 2 (does not include file names)", MADFormatVersion.Type2)
+ }));
+ _dfr.ImportOptions.Add(new CustomOptionChoice("FormatVersion", "Format &version:", true, new CustomOptionFieldChoice[]
+ {
+ new CustomOptionFieldChoice("Type 1 (includes file names)", MADFormatVersion.Type1, true),
+ new CustomOptionFieldChoice("Type 2 (does not include file names)", MADFormatVersion.Type2)
+ }));
+ _dfr.Filters.Add("Gremlin Interactive - Actua Soccer MAD archive", new string[] { "*.mad" });
+ _dfr.Sources.Add("http://wiki.xentax.com/index.php?title=GRAF:Actua_Soccer_MAD");
+ }
+ return _dfr;
+ }
+
+ private MADFormatVersion mvarFormatVersion = MADFormatVersion.Type1;
+ public MADFormatVersion FormatVersion { get { return mvarFormatVersion; } set { mvarFormatVersion = value; } }
+
+ protected override void LoadInternal(ref ObjectModel objectModel)
+ {
+ FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
+ if (fsom == null) throw new ObjectModelNotSupportedException();
+
+ Reader reader = base.Accessor.Reader;
+
+ long currentOffset = reader.Accessor.Position;
+
+ // calculate count of files
+ if (mvarFormatVersion == MADFormatVersion.Type1)
+ {
+ reader.ReadFixedLengthString(16);
+ }
+ uint firstFileOffset = reader.ReadUInt32();
+
+ uint fileCount = 0;
+ switch (mvarFormatVersion)
+ {
+ case MADFormatVersion.Type1:
+ {
+ fileCount = (uint)((double)firstFileOffset / 24);
+ break;
+ }
+ case MADFormatVersion.Type2:
+ {
+ fileCount = (uint)((double)firstFileOffset / 8);
+ break;
+ }
+ }
+
+ reader.Accessor.Seek(currentOffset, SeekOrigin.Begin);
+
+ for (uint i = 0; i < fileCount; i++)
+ {
+ string fileName = i.ToString().PadLeft(8, '0');
+ if (mvarFormatVersion == MADFormatVersion.Type1)
+ {
+ fileName = reader.ReadFixedLengthString(16).TrimNull();
+ }
+ uint offset = reader.ReadUInt32();
+ uint length = reader.ReadUInt32();
+
+ File file = fsom.AddFile(fileName);
+ file.Size = length;
+ file.Properties.Add("reader", reader);
+ file.Properties.Add("offset", offset);
+ file.Properties.Add("length", length);
+ file.DataRequest += file_DataRequest;
+ }
+ }
+ private void file_DataRequest(object sender, DataRequestEventArgs e)
+ {
+ File file = (sender as File);
+ Reader reader = (Reader)file.Properties["reader"];
+ uint offset = (uint)file.Properties["offset"];
+ uint length = (uint)file.Properties["length"];
+ reader.Seek(offset, SeekOrigin.Begin);
+ e.Data = reader.ReadBytes(length);
+ }
+ protected override void SaveInternal(ObjectModel objectModel)
+ {
+ FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
+ if (fsom == null) throw new ObjectModelNotSupportedException();
+
+ File[] files = fsom.GetAllFiles();
+
+ Writer writer = base.Accessor.Writer;
+ uint offset = 0;
+
+ for (uint i = 0; i < files.Length; i++)
+ {
+ offset += 8;
+ if (mvarFormatVersion == MADFormatVersion.Type1) offset += 16;
+ }
+ for (uint i = 0; i < files.Length; i++)
+ {
+ if (mvarFormatVersion == MADFormatVersion.Type1) writer.WriteFixedLengthString(files[i].Name, 16);
+ uint length = (uint)files[i].Size;
+ writer.WriteUInt32(offset);
+ writer.WriteUInt32(length);
+ offset += length;
+ }
+ for (uint i = 0; i < files.Length; i++)
+ {
+ writer.WriteBytes(files[i].GetDataAsByteArray());
+ }
+ writer.Flush();
+ }
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADFormatVersion.cs b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADFormatVersion.cs
new file mode 100644
index 00000000..63c5f430
--- /dev/null
+++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/GremlinInteractive/ActuaSoccer/MAD/MADFormatVersion.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace UniversalEditor.DataFormats.FileSystem.GremlinInteractive.ActuaSoccer.MAD
+{
+ public enum MADFormatVersion
+ {
+ Type1,
+ Type2
+ }
+}
diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj
index 4ab56280..cba1a443 100644
--- a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj
+++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/UniversalEditor.Plugins.FileSystem.csproj
@@ -96,6 +96,8 @@
+
+