From f9b4693aae4079585cac814d7c1c10332d4dcbf6 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 14 Dec 2022 21:48:22 -0800 Subject: [PATCH] Add block table parsing to MoPaQ (nw) --- BurnOutSharp.Builder/MoPaQ.cs | 156 +++++++++++++++++++++++++++++++--- 1 file changed, 145 insertions(+), 11 deletions(-) diff --git a/BurnOutSharp.Builder/MoPaQ.cs b/BurnOutSharp.Builder/MoPaQ.cs index dc212b64..76cf49cf 100644 --- a/BurnOutSharp.Builder/MoPaQ.cs +++ b/BurnOutSharp.Builder/MoPaQ.cs @@ -348,10 +348,76 @@ namespace BurnOutSharp.Builder #region Block Table - ulong blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; - if (blockTableOffset != 0) + // Version 1 + if (archive.ArchiveHeader.FormatVersion == 0) { - // TODO: Read in Block Table + // If we have a block table + long blockTableOffset = archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + archive.ArchiveHeader.BlockTableSize; + + // Read in the block table + var blockTable = new List(); + + while (blockTableOffset < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data, ref blockTableOffset); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } + } + + // Version 2 and 3 + else if (archive.ArchiveHeader.FormatVersion == 1 || archive.ArchiveHeader.FormatVersion == 2) + { + // If we have a block table + long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + archive.ArchiveHeader.BlockTableSize; + + // Read in the block table + var blockTable = new List(); + + while (blockTableOffset < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data, ref blockTableOffset); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } + } + + // Version 4 + else if (archive.ArchiveHeader.FormatVersion == 3) + { + // If we have a block table + long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + (long)archive.ArchiveHeader.BlockTableSizeLong; + + // Read in the block table + var blockTable = new List(); + + while (blockTableOffset < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data, ref blockTableOffset); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } } #endregion @@ -586,16 +652,18 @@ namespace BurnOutSharp.Builder /// Byte array to parse /// Offset into the byte array /// Filled block entry on success, null on error - private static BlockEntry ParseBlockEntry(byte[] data, ref int offset) + private static BlockEntry ParseBlockEntry(byte[] data, ref long offset) { // TODO: Use marshalling here instead of building BlockEntry blockEntry = new BlockEntry(); + int intOffset = (int)offset; - blockEntry.FilePosition = data.ReadUInt32(ref offset); - blockEntry.CompressedSize = data.ReadUInt32(ref offset); - blockEntry.UncompressedSize = data.ReadUInt32(ref offset); - blockEntry.Flags = (FileFlags)data.ReadUInt32(ref offset); + blockEntry.FilePosition = data.ReadUInt32(ref intOffset); + blockEntry.CompressedSize = data.ReadUInt32(ref intOffset); + blockEntry.UncompressedSize = data.ReadUInt32(ref intOffset); + blockEntry.Flags = (FileFlags)data.ReadUInt32(ref intOffset); + offset = intOffset; return blockEntry; } @@ -765,10 +833,76 @@ namespace BurnOutSharp.Builder #region Block Table - ulong blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; - if (blockTableOffset != 0) + // Version 1 + if (archive.ArchiveHeader.FormatVersion == 0) { - // TODO: Read in Block Table + // If we have a block table + long blockTableOffset = archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + archive.ArchiveHeader.BlockTableSize; + + // Read in the block table + var blockTable = new List(); + + while (data.Position < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } + } + + // Version 2 and 3 + else if (archive.ArchiveHeader.FormatVersion == 1 || archive.ArchiveHeader.FormatVersion == 2) + { + // If we have a block table + long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + archive.ArchiveHeader.BlockTableSize; + + // Read in the block table + var blockTable = new List(); + + while (data.Position < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } + } + + // Version 4 + else if (archive.ArchiveHeader.FormatVersion == 3) + { + // If we have a block table + long blockTableOffset = ((uint)archive.ArchiveHeader.BlockTablePositionHi << 23) | archive.ArchiveHeader.BlockTablePosition; + if (blockTableOffset != 0) + { + // Find the ending offset based on size + long blockTableEnd = blockTableOffset + (long)archive.ArchiveHeader.BlockTableSizeLong; + + // Read in the block table + var blockTable = new List(); + + while (data.Position < blockTableEnd) + { + var blockEntry = ParseBlockEntry(data); + if (blockEntry == null) + return null; + } + + archive.BlockTable = blockTable.ToArray(); + } } #endregion