public void Save(string file) { Console.WriteLine(file); using (var bw = new BinaryWriter(File.Create(file))) { // skip header until later ------------------------------------------------------------------------------------ bw.Pad(Header.HeaderLength); if (EventGroupsA.Count != EventGroupsB.Count) { throw new Exception($"Event groups A and B count don't match ({EventGroupsA.Count}, {EventGroupsB.Count})"); } int numGroups = EventGroupsA.Count; // write the list containing the number of items in each subgroup ---------------------------------------------- for (int i = 0; i < numGroups; i++) { var groupA = EventGroupsA[i]; var groupB = EventGroupsB[i]; if (groupA.Count != groupB.Count) { throw new Exception($"Event group {i} does not contain the same number of events in A and B"); } bw.Write(groupA.Count); } // skip offset table until later ------------------------------------------------------------------------------ int numOffsets = EventGroupsA.Sum(i => i.Count); // the +1 is because there's an 'end' one too // *4 for each byte in an offset entry // *2 for the two tables A and B int dataStart = OffsetTableStart + (numOffsets + 1) * 4 * 2; bw.BaseStream.Seek(dataStart, SeekOrigin.Begin); // write data, keep track of offsets ---------------------------------------------------------------------------- List <List <int> > offsetsA = new List <List <int> >(); long startOffsetA = bw.BaseStream.Position; foreach (var group in EventGroupsA) { List <int> subgroupOffsets = new List <int>(); offsetsA.Add(subgroupOffsets); foreach (var(b, e) in group) { subgroupOffsets.Add((int)(bw.BaseStream.Position - startOffsetA)); bw.Write(b); e.WriteTo(bw); } } List <List <int> > offsetsB = new List <List <int> >(); long startOffsetB = bw.BaseStream.Position; int tableBDataOffset = (int)(startOffsetB - startOffsetA); foreach (var group in EventGroupsB) { List <int> subgroupOffsets = new List <int>(); offsetsB.Add(subgroupOffsets); foreach (var e in group) { subgroupOffsets.Add((int)(bw.BaseStream.Position - startOffsetB)); e.WriteTo(bw); } } int dataEndB = (int)(bw.BaseStream.Position - startOffsetB); // pad the file to be divisible by 0x10 while (bw.BaseStream.Length % 8 != 0) { bw.Pad(1); } // write offsets ---------------------------------------------------------------------------------------------- bw.BaseStream.Position = OffsetTableStart; foreach (var offsets in offsetsA) { foreach (var o in offsets) { bw.Write(o); } } bw.Write(tableBDataOffset); foreach (var offsets in offsetsB) { foreach (var o in offsets) { bw.Write(o); } } bw.Write(dataEndB); // write the header ---------------------------------------------------------------------------------------------- var header = new Header() { FortyEight = 0x48, FileId = FileId, Unknown = HeaderUnknown, NumGroups = numGroups, TableBDataOffset = tableBDataOffset, FileLength = (int)bw.BaseStream.Length, NumOffsets = numOffsets }; bw.BaseStream.Position = 0; header.WriteTo(bw); } }
public EVE(string file) { Console.WriteLine(file); using (var br = new BinaryReader(File.OpenRead(file))) { // Header ------------------------------------------------------------------------------------ var header = new Header(br); FileId = header.FileId; HeaderUnknown = header.Unknown; //Console.WriteLine("GroupItemCounts:"); int[] groupItemCounts = new int[header.NumGroups]; for (int i = 0; i < header.NumGroups; i++) { groupItemCounts[i] = br.ReadInt32(); //Console.WriteLine($" 0x{groupItemCounts[i]:X}"); } // Offset Tables ------------------------------------------------------------------------------- //Console.WriteLine("OffsetTableA:"); br.BaseStream.Position = OffsetTableStart; int[][] groupsA = new int[header.NumGroups][]; for (int groupId = 0; groupId < header.NumGroups; groupId++) { //Console.WriteLine($" Group {groupId} (numItems:{groupItemCounts[groupId]}):"); groupsA[groupId] = new int[groupItemCounts[groupId]]; for (int idWithinGroup = 0; idWithinGroup < groupItemCounts[groupId]; idWithinGroup++) { groupsA[groupId][idWithinGroup] = br.ReadInt32(); //Console.WriteLine($" 0x{groupsA[groupId][idWithinGroup]:X} (id: {idWithinGroup})"); } } Debug.Assert(groupsA.Sum(i => i.Length) == header.NumOffsets); var shift = br.ReadUInt32(); if (shift != header.TableBDataOffset) { throw new InvalidDataException("Listed offset doesnt match earlier value"); } //Console.WriteLine("OffsetTableB:"); int[][] groupsB = new int[header.NumGroups][]; for (int groupId = 0; groupId < header.NumGroups; groupId++) { //Console.WriteLine($" Group {groupId}:"); groupsB[groupId] = new int[groupItemCounts[groupId]]; for (int idWithinGroup = 0; idWithinGroup < groupItemCounts[groupId]; idWithinGroup++) { groupsB[groupId][idWithinGroup] = br.ReadInt32(); //Console.WriteLine($" 0x{groupsB[groupId][idWithinGroup]:X} (id: {idWithinGroup})"); } } Debug.Assert(groupsB.Sum(i => i.Length) == header.NumOffsets); var end = br.ReadInt32(); //Console.WriteLine($"END OF OFFSETS VALUE = 0x{end:X}"); // Data --------------------------------------------------------------------------------------- var startOffsetA = br.BaseStream.Position; for (int a = 0; a < groupsA.Length; a++) { int[] group = groupsA[a]; var eveGroup = new List <(byte[], Event)>(); EventGroupsA.Add(eveGroup); for (int i = 0; i < group.Length; i++) { var eventOffset = group[i]; br.BaseStream.Position = startOffsetA + eventOffset; byte[] unknown = br.ReadBytes(0x40); eveGroup.Add((unknown, new Event(br))); } } var startOffsetB = br.BaseStream.Position; //Console.WriteLine("START OFFSET B: 0x{0:X}", startOffsetB); var expectedStartOffsetB = startOffsetA + header.TableBDataOffset; Debug.Assert(startOffsetB == expectedStartOffsetB, $"Start offset of B is unexpected: 0x{startOffsetB:X} (expected: 0x{expectedStartOffsetB:X})"); for (int b = 0; b < groupsB.Length; b++) { int[] group = groupsB[b]; var eveGroup = new List <Event>(); EventGroupsB.Add(eveGroup); for (int i = 0; i < group.Length; i++) { var eventOffset = group[i]; br.BaseStream.Position = startOffsetB + eventOffset; eveGroup.Add(new Event(br)); } } // ---------------------------------------------------------------------------- } }