changeset 3:1a54f6afafe7

Re #84 and #85: Support Army Builder v2/v3 files * Separate out the two versions of file * Restructure file loader to load v2 files correctly * Tidy up file extractor (still not working)
author IBBoard <dev@ibboard.co.uk>
date Sun, 17 May 2009 18:40:36 +0000
parents d5ba733cd289
children d2f7826147eb
files ABFile.cs ABv2File.cs ABv3File.cs Extractors/ArmyBuilderFileExtractor.cs IBBoard.ArmyBuilder.API.csproj Loaders/ArmyBuilderABFileLoader.cs
diffstat 6 files changed, 268 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/ABFile.cs	Mon Apr 20 19:28:01 2009 +0000
+++ b/ABFile.cs	Sun May 17 18:40:36 2009 +0000
@@ -15,19 +15,12 @@
 	/// A .ab file (Army Builder's main data definition file). .ab files contain details of the application requirements for a game system,
 	/// details of the game system, and all of the data files for that game system (including race data).
 	/// </summary>
-	public class ABFile
+	public abstract class ABFile
 	{
 		private FileInfo file;
 		private string header = "";
-		private string gameName = "";
-		private string folderName = "";
-		private string releaseMajor = "";
-		private string releaseMinor = "";
-		private string requiredMajorVersion = "";
-		private string requiredMinorVersion = "";
-		private string uniqueID = "";
-		private string exporter = "";
 		private string comment = "";
+		private int fileTablePosition = 0;
 		private List<FileTableEntry> files;
 		
 		public ABFile(String filePath) : this(new FileInfo(filePath))
@@ -90,112 +83,6 @@
 			}
 		}
 
-		public string GameName
-		{
-			get
-			{
-				return gameName;
-			}
-			set
-			{
-				gameName = value;
-			}
-		}
-
-		public string FolderName
-		{
-			get
-			{
-				return folderName;
-			}
-			set
-			{
-				folderName = value;
-			}
-		}
-
-		public string Release
-		{
-			get { return ReleaseMajor + "." + ReleaseMinor; }
-		}
-
-		public string ReleaseMajor
-		{
-			get
-			{
-				return releaseMajor;
-			}
-			set
-			{
-				releaseMajor = value;
-			}
-		}
-
-		public string ReleaseMinor
-		{
-			get
-			{
-				return releaseMinor;
-			}
-			set
-			{
-				releaseMinor = value;
-			}
-		}
-
-		public string RequiredVersion
-		{
-			get { return RequiredMajorVersion + "." + RequiredMinorVersion; }
-		}
-
-		public string RequiredMajorVersion
-		{
-			get
-			{
-				return requiredMajorVersion;
-			}
-			set
-			{
-				requiredMajorVersion = value;
-			}
-		}
-
-		public string RequiredMinorVersion
-		{
-			get
-			{
-				return requiredMinorVersion;
-			}
-			set
-			{
-				requiredMinorVersion = value;
-			}
-		}
-
-		public string UniqueID
-		{
-			get
-			{
-				return uniqueID;
-			}
-			set
-			{
-				uniqueID = value;
-			}
-		}
-
-		public string Exporter
-		{
-			get
-			{
-				return exporter;
-			}
-			set
-			{
-				exporter = value;
-			}
-		}
-
 		public string Comment
 		{
 			get
@@ -207,5 +94,17 @@
 				comment = value;
 			}
 		}
+
+		public int FileTablePosition
+		{
+			get
+			{
+				return fileTablePosition;
+			}
+			set
+			{
+				fileTablePosition = value;
+			}
+		}			
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ABv2File.cs	Sun May 17 18:40:36 2009 +0000
@@ -0,0 +1,21 @@
+//  This file (ABv2File.cs) is a part of the IBBoard.ArmyBuilder.API project and is copyright 2009 IBBoard
+// 
+//  The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license.
+// 
+
+using System;
+using System.IO;
+
+namespace IBBoard.ArmyBuilder.API
+{
+	public class ABv2File : ABFile
+	{
+		public ABv2File(String filePath) : base(new FileInfo(filePath))
+		{
+		}
+
+		public ABv2File(FileInfo file) : base(file)
+		{
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ABv3File.cs	Sun May 17 18:40:36 2009 +0000
@@ -0,0 +1,136 @@
+//  This file (ABv3File.cs) is a part of the IBBoard.ArmyBuilder.API project and is copyright 2009 IBBoard
+// 
+//  The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license.
+// 
+
+using System;
+using System.IO;
+
+namespace IBBoard.ArmyBuilder.API
+{
+	public class ABv3File : ABFile
+	{
+		private string gameName = "";
+		private string folderName = "";
+		private string releaseMajor = "";
+		private string releaseMinor = "";
+		private string requiredMajorVersion = "";
+		private string requiredMinorVersion = "";
+		private string uniqueID = "";
+		private string exporter = "";
+		
+		public ABv3File(String filePath) : base(new FileInfo(filePath))
+		{
+		}
+
+		public ABv3File(FileInfo file) : base(file)
+		{
+		}
+
+		public string GameName
+		{
+			get
+			{
+				return gameName;
+			}
+			set
+			{
+				gameName = value;
+			}
+		}
+
+		public string FolderName
+		{
+			get
+			{
+				return folderName;
+			}
+			set
+			{
+				folderName = value;
+			}
+		}
+
+		public string Release
+		{
+			get { return ReleaseMajor + "." + ReleaseMinor; }
+		}
+
+		public string ReleaseMajor
+		{
+			get
+			{
+				return releaseMajor;
+			}
+			set
+			{
+				releaseMajor = value;
+			}
+		}
+
+		public string ReleaseMinor
+		{
+			get
+			{
+				return releaseMinor;
+			}
+			set
+			{
+				releaseMinor = value;
+			}
+		}
+
+		public string RequiredVersion
+		{
+			get { return RequiredMajorVersion + "." + RequiredMinorVersion; }
+		}
+
+		public string RequiredMajorVersion
+		{
+			get
+			{
+				return requiredMajorVersion;
+			}
+			set
+			{
+				requiredMajorVersion = value;
+			}
+		}
+
+		public string RequiredMinorVersion
+		{
+			get
+			{
+				return requiredMinorVersion;
+			}
+			set
+			{
+				requiredMinorVersion = value;
+			}
+		}
+
+		public string UniqueID
+		{
+			get
+			{
+				return uniqueID;
+			}
+			set
+			{
+				uniqueID = value;
+			}
+		}
+
+		public string Exporter
+		{
+			get
+			{
+				return exporter;
+			}
+			set
+			{
+				exporter = value;
+			}
+		}
+	}
+}
--- a/Extractors/ArmyBuilderFileExtractor.cs	Mon Apr 20 19:28:01 2009 +0000
+++ b/Extractors/ArmyBuilderFileExtractor.cs	Sun May 17 18:40:36 2009 +0000
@@ -5,8 +5,6 @@
 
 using System;
 using System.IO;
-//using ICSharpCode.SharpZipLib.BZip2;
-//using ICSharpCode.SharpZipLib.GZip;
 using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
 using IBBoard.ArmyBuilder.API;
 
@@ -15,30 +13,26 @@
 	public class ArmyBuilderFileExtractor
 	{		
 		public static byte[] GetFileEntryContent(FileTableEntry entry)
-		{			
-			//BZip2InputStream zipped = null;
-			//GZipInputStream zipped = null;
+		{
 			InflaterInputStream zipped = null;
 			byte[] byteArr = new byte[entry.FileSize];
 			
 			try
 			{
-				byte [] compressed = GetFileEntryCompressedContent(entry);
-				MemoryStream ms = new MemoryStream(compressed, 0, compressed.Length);
+				byte[] compressed = GetFileEntryCompressedContent(entry);
+				MemoryStream ms = new MemoryStream(compressed);
 				ms.Seek(0, SeekOrigin.Begin);
-				//zipped = new BZip2InputStream(ms);
-				//zipped = new GZipInputStream(ms);
-				zipped = new InflaterInputStream(ms);
-								
+				zipped = new InflaterInputStream(ms, new Inflater(true));
+
 				int size = 0;
-				int offset = 0;
+				int pos = 0;
 
 				do
 				{
-					size = zipped.Read(byteArr, offset, byteArr.Length);
-					offset+= size;
-				} 
-				while (size > 0);
+					size = zipped.Read(byteArr, pos, byteArr.Length);
+					pos+=size;
+				}
+				while (size > 0);					                   
 			}
 			finally
 			{
--- a/IBBoard.ArmyBuilder.API.csproj	Mon Apr 20 19:28:01 2009 +0000
+++ b/IBBoard.ArmyBuilder.API.csproj	Sun May 17 18:40:36 2009 +0000
@@ -40,6 +40,8 @@
     <Compile Include="Extractors\ArmyBuilderFileExtractor.cs" />
     <Compile Include="FileTableEntry.cs" />
     <Compile Include="Loaders\ArmyBuilderABFileLoader.cs" />
+    <Compile Include="ABv3File.cs" />
+    <Compile Include="ABv2File.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="COPYING.GPL" />
--- a/Loaders/ArmyBuilderABFileLoader.cs	Mon Apr 20 19:28:01 2009 +0000
+++ b/Loaders/ArmyBuilderABFileLoader.cs	Sun May 17 18:40:36 2009 +0000
@@ -11,21 +11,99 @@
 	public class ArmyBuilderABFileLoader
 	{
 		private static byte HEADER_DELIMITER = 0x09;
+		private static byte HEADER_TYPE_DELIMITER = 0x3A;
+		private static byte TABLE_HEADER_OFFSET_FROM = 4;
+		private static byte FILE_TABLE_OFFSET_LENGTH = 2;
 
 		public static ABFile LoadFile(FileInfo file)
 		{
-			ABFile abFile = new ABFile(file);
-			LoadData(abFile);
+			ABFile abFile = ReadFileInfo(file);
+			ReadFileTable(abFile);
+			return abFile;
+		}
+
+		private static ABFile ReadFileInfo(FileInfo file)
+		{			
+			BinaryReaderBigEndian reader = new BinaryReaderBigEndian(file.OpenRead());
+			ABFile abFile = null;
+
+			try
+			{
+				abFile = ReadFileInfo(file, reader);
+			}
+			finally
+			{
+				reader.Close();
+			}	
+			
+			return abFile;
+		}
+
+		private static ABFile ReadFileInfo(FileInfo file, BinaryReaderBigEndian reader)
+		{
+			int tableOffset = reader.ReadInt();
+			reader.Move(tableOffset);
+			ushort fileTableOffset = reader.ReadUShort();
+			string header = reader.ReadDelimitedString(HEADER_TYPE_DELIMITER);
+
+			ABFile abFile = CreateFile(file, header);
+			ReadExtraHeaders(abFile, reader);
+			int fileTablePosition = TABLE_HEADER_OFFSET_FROM + tableOffset + FILE_TABLE_OFFSET_LENGTH + fileTableOffset;
+			abFile.FileTablePosition = fileTablePosition;
+			int readerPosition = (int)reader.Position;
+
+			if (fileTablePosition > readerPosition)
+			{
+				abFile.Comment = reader.ReadString(fileTablePosition - readerPosition);
+			}
+
 			return abFile;
 		}
-		
-		private static void LoadData(ABFile abFile)
+
+		private static ABFile CreateFile(FileInfo file, string header)
 		{
+			ABFile abFile = null;
+			header = header.Trim();
+			
+			if ("LWDExport".Equals(header))
+			{
+				abFile = new ABv3File(file);
+			}
+			else if ("ArmyBuilder".Equals(header))
+			{
+				abFile = new ABv2File(file);
+			}
+			else
+			{
+				throw new InvalidDataException("Unsupported file table header: "+header);
+			}
+
+			abFile.Header = header;
+			return abFile;
+		}
+
+		private static void ReadExtraHeaders(ABFile abFile, BinaryReaderBigEndian reader)
+		{
+			if (abFile is ABv3File)
+			{
+				ABv3File ab3File = (ABv3File)abFile;
+				ab3File.GameName = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.FolderName = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.ReleaseMajor = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.ReleaseMinor = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.RequiredMajorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.RequiredMinorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.UniqueID = reader.ReadDelimitedString(HEADER_DELIMITER);
+				ab3File.Exporter = reader.ReadDelimitedString(HEADER_DELIMITER);
+			}
+		}
+
+		private static void ReadFileTable(ABFile abFile)
+		{	
 			BinaryReaderBigEndian reader = new BinaryReaderBigEndian(abFile.File.OpenRead());
 
 			try
 			{
-				ReadFileInfo(abFile, reader);
 				ReadFileTable(abFile, reader);
 			}
 			finally
@@ -34,37 +112,10 @@
 			}
 		}
 
-		private static void ReadFileInfo(ABFile abFile, BinaryReaderBigEndian reader)
-		{
-			int tableOffset = reader.ReadInt();
-			reader.Move(tableOffset);
-			ushort fileTableOffset = reader.ReadUShort();
-			abFile.Header = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.GameName = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.FolderName = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.ReleaseMajor = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.ReleaseMinor = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.RequiredMajorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.RequiredMinorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.UniqueID = reader.ReadDelimitedString(HEADER_DELIMITER);
-			abFile.Exporter = reader.ReadDelimitedString(HEADER_DELIMITER);
-			int bytesRead = CalculateFileInfoSize(abFile);
-
-			if (fileTableOffset > bytesRead)
-			{
-				abFile.Comment = reader.ReadString(fileTableOffset - bytesRead);
-			}			
-		}
-
-		private static int CalculateFileInfoSize(ABFile file)
-		{
-			return file.Header.Length + file.GameName.Length + file.FolderName.Length + file.ReleaseMajor.Length + file.ReleaseMinor.Length +
-				file.RequiredMajorVersion.Length + file.RequiredMinorVersion.Length + file.UniqueID.Length + file.Exporter.Length + 9;
-		}
-
 		private static void ReadFileTable(ABFile abFile, BinaryReaderBigEndian reader)
-		{
+		{			
 			FileTableEntry entry = null;
+			reader.Seek(abFile.FileTablePosition);
 			
 			do
 			{