comparison Loaders/ArmyBuilderABFileLoader.cs @ 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 ec77b60e5369
comparison
equal deleted inserted replaced
2:d5ba733cd289 3:1a54f6afafe7
9 namespace IBBoard.ArmyBuilder.API.Loaders 9 namespace IBBoard.ArmyBuilder.API.Loaders
10 { 10 {
11 public class ArmyBuilderABFileLoader 11 public class ArmyBuilderABFileLoader
12 { 12 {
13 private static byte HEADER_DELIMITER = 0x09; 13 private static byte HEADER_DELIMITER = 0x09;
14 private static byte HEADER_TYPE_DELIMITER = 0x3A;
15 private static byte TABLE_HEADER_OFFSET_FROM = 4;
16 private static byte FILE_TABLE_OFFSET_LENGTH = 2;
14 17
15 public static ABFile LoadFile(FileInfo file) 18 public static ABFile LoadFile(FileInfo file)
16 { 19 {
17 ABFile abFile = new ABFile(file); 20 ABFile abFile = ReadFileInfo(file);
18 LoadData(abFile); 21 ReadFileTable(abFile);
19 return abFile; 22 return abFile;
20 } 23 }
21 24
22 private static void LoadData(ABFile abFile) 25 private static ABFile ReadFileInfo(FileInfo file)
26 {
27 BinaryReaderBigEndian reader = new BinaryReaderBigEndian(file.OpenRead());
28 ABFile abFile = null;
29
30 try
31 {
32 abFile = ReadFileInfo(file, reader);
33 }
34 finally
35 {
36 reader.Close();
37 }
38
39 return abFile;
40 }
41
42 private static ABFile ReadFileInfo(FileInfo file, BinaryReaderBigEndian reader)
23 { 43 {
44 int tableOffset = reader.ReadInt();
45 reader.Move(tableOffset);
46 ushort fileTableOffset = reader.ReadUShort();
47 string header = reader.ReadDelimitedString(HEADER_TYPE_DELIMITER);
48
49 ABFile abFile = CreateFile(file, header);
50 ReadExtraHeaders(abFile, reader);
51 int fileTablePosition = TABLE_HEADER_OFFSET_FROM + tableOffset + FILE_TABLE_OFFSET_LENGTH + fileTableOffset;
52 abFile.FileTablePosition = fileTablePosition;
53 int readerPosition = (int)reader.Position;
54
55 if (fileTablePosition > readerPosition)
56 {
57 abFile.Comment = reader.ReadString(fileTablePosition - readerPosition);
58 }
59
60 return abFile;
61 }
62
63 private static ABFile CreateFile(FileInfo file, string header)
64 {
65 ABFile abFile = null;
66 header = header.Trim();
67
68 if ("LWDExport".Equals(header))
69 {
70 abFile = new ABv3File(file);
71 }
72 else if ("ArmyBuilder".Equals(header))
73 {
74 abFile = new ABv2File(file);
75 }
76 else
77 {
78 throw new InvalidDataException("Unsupported file table header: "+header);
79 }
80
81 abFile.Header = header;
82 return abFile;
83 }
84
85 private static void ReadExtraHeaders(ABFile abFile, BinaryReaderBigEndian reader)
86 {
87 if (abFile is ABv3File)
88 {
89 ABv3File ab3File = (ABv3File)abFile;
90 ab3File.GameName = reader.ReadDelimitedString(HEADER_DELIMITER);
91 ab3File.FolderName = reader.ReadDelimitedString(HEADER_DELIMITER);
92 ab3File.ReleaseMajor = reader.ReadDelimitedString(HEADER_DELIMITER);
93 ab3File.ReleaseMinor = reader.ReadDelimitedString(HEADER_DELIMITER);
94 ab3File.RequiredMajorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
95 ab3File.RequiredMinorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
96 ab3File.UniqueID = reader.ReadDelimitedString(HEADER_DELIMITER);
97 ab3File.Exporter = reader.ReadDelimitedString(HEADER_DELIMITER);
98 }
99 }
100
101 private static void ReadFileTable(ABFile abFile)
102 {
24 BinaryReaderBigEndian reader = new BinaryReaderBigEndian(abFile.File.OpenRead()); 103 BinaryReaderBigEndian reader = new BinaryReaderBigEndian(abFile.File.OpenRead());
25 104
26 try 105 try
27 { 106 {
28 ReadFileInfo(abFile, reader);
29 ReadFileTable(abFile, reader); 107 ReadFileTable(abFile, reader);
30 } 108 }
31 finally 109 finally
32 { 110 {
33 reader.Close(); 111 reader.Close();
34 } 112 }
35 } 113 }
36 114
37 private static void ReadFileInfo(ABFile abFile, BinaryReaderBigEndian reader)
38 {
39 int tableOffset = reader.ReadInt();
40 reader.Move(tableOffset);
41 ushort fileTableOffset = reader.ReadUShort();
42 abFile.Header = reader.ReadDelimitedString(HEADER_DELIMITER);
43 abFile.GameName = reader.ReadDelimitedString(HEADER_DELIMITER);
44 abFile.FolderName = reader.ReadDelimitedString(HEADER_DELIMITER);
45 abFile.ReleaseMajor = reader.ReadDelimitedString(HEADER_DELIMITER);
46 abFile.ReleaseMinor = reader.ReadDelimitedString(HEADER_DELIMITER);
47 abFile.RequiredMajorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
48 abFile.RequiredMinorVersion = reader.ReadDelimitedString(HEADER_DELIMITER);
49 abFile.UniqueID = reader.ReadDelimitedString(HEADER_DELIMITER);
50 abFile.Exporter = reader.ReadDelimitedString(HEADER_DELIMITER);
51 int bytesRead = CalculateFileInfoSize(abFile);
52
53 if (fileTableOffset > bytesRead)
54 {
55 abFile.Comment = reader.ReadString(fileTableOffset - bytesRead);
56 }
57 }
58
59 private static int CalculateFileInfoSize(ABFile file)
60 {
61 return file.Header.Length + file.GameName.Length + file.FolderName.Length + file.ReleaseMajor.Length + file.ReleaseMinor.Length +
62 file.RequiredMajorVersion.Length + file.RequiredMinorVersion.Length + file.UniqueID.Length + file.Exporter.Length + 9;
63 }
64
65 private static void ReadFileTable(ABFile abFile, BinaryReaderBigEndian reader) 115 private static void ReadFileTable(ABFile abFile, BinaryReaderBigEndian reader)
66 { 116 {
67 FileTableEntry entry = null; 117 FileTableEntry entry = null;
118 reader.Seek(abFile.FileTablePosition);
68 119
69 do 120 do
70 { 121 {
71 entry = ReadFileTableEntry(reader); 122 entry = ReadFileTableEntry(reader);
72 abFile.AddFileTableEntry(entry); 123 abFile.AddFileTableEntry(entry);