diff --git a/BinaryObjectScanner.Test/Data/StaticChecksTests.cs b/BinaryObjectScanner.Test/Data/StaticChecksTests.cs new file mode 100644 index 00000000..e69de29b diff --git a/BinaryObjectScanner.Test/ScannerTests.cs b/BinaryObjectScanner.Test/ScannerTests.cs new file mode 100644 index 00000000..e69de29b diff --git a/BinaryObjectScanner/FileType/AACSMediaKeyBlock.cs b/BinaryObjectScanner/FileType/AACSMediaKeyBlock.cs index 0dfb9ee3..5390f221 100644 --- a/BinaryObjectScanner/FileType/AACSMediaKeyBlock.cs +++ b/BinaryObjectScanner/FileType/AACSMediaKeyBlock.cs @@ -31,7 +31,7 @@ namespace BinaryObjectScanner.FileType return null; // Derive the version, if possible - var typeAndVersion = Array.Find(mkb.Model.Records ?? [], r => r?.RecordType == SabreTools.Models.AACS.RecordType.TypeAndVersion); + var typeAndVersion = Array.Find(mkb.Records ?? [], r => r?.RecordType == SabreTools.Models.AACS.RecordType.TypeAndVersion); if (typeAndVersion == null) return "AACS (Unknown Version)"; else diff --git a/BinaryObjectScanner/FileType/BDPlusSVM.cs b/BinaryObjectScanner/FileType/BDPlusSVM.cs index d670466b..cbfd4b6b 100644 --- a/BinaryObjectScanner/FileType/BDPlusSVM.cs +++ b/BinaryObjectScanner/FileType/BDPlusSVM.cs @@ -30,11 +30,8 @@ namespace BinaryObjectScanner.FileType if (svm == null) return null; - // Format the date - string date = $"{svm.Model.Year:0000}/{svm.Model.Month:00}/{svm.Model.Day:00}"; - // Return the formatted value - return $"BD+ {date}"; + return $"BD+ {svm.Date}"; } catch (Exception ex) { diff --git a/BinaryObjectScanner/FileType/BSP.cs b/BinaryObjectScanner/FileType/BSP.cs index c829d4bd..8b62d565 100644 --- a/BinaryObjectScanner/FileType/BSP.cs +++ b/BinaryObjectScanner/FileType/BSP.cs @@ -1,7 +1,6 @@ using System; using System.IO; using BinaryObjectScanner.Interfaces; -using SabreTools.Models.BSP; namespace BinaryObjectScanner.FileType { @@ -34,7 +33,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAllLumps(bsp, outDir); + bsp.ExtractAllLumps(outDir); return true; } @@ -44,91 +43,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all lumps from the BSP to an output directory - /// - /// Output directory to write to - /// True if all lumps extracted, false otherwise - public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.BSP item, string outputDirectory) - { - // If we have no lumps - if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0) - return false; - - // Loop through and extract all lumps to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.Header.Lumps.Length; i++) - { - allExtracted &= ExtractLump(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a lump from the BSP to an output directory by index - /// - /// Lump index to extract - /// Output directory to write to - /// True if the lump extracted, false otherwise - public static bool ExtractLump(SabreTools.Serialization.Wrappers.BSP item, int index, string outputDirectory) - { - // If we have no lumps - if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0) - return false; - - // If the lumps index is invalid - if (index < 0 || index >= item.Model.Header.Lumps.Length) - return false; - - // Get the lump - var lump = item.Model.Header.Lumps[index]; - if (lump == null) - return false; - - // Read the data - var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length); - if (data == null) - return false; - - // Create the filename - string filename = $"lump_{index}.bin"; - switch ((LumpType)index) - { - case LumpType.LUMP_ENTITIES: - filename = "entities.ent"; - break; - case LumpType.LUMP_TEXTURES: - filename = "texture_data.bin"; - break; - } - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/GCF.cs b/BinaryObjectScanner/FileType/GCF.cs index 1b39dbb3..2c84ff5b 100644 --- a/BinaryObjectScanner/FileType/GCF.cs +++ b/BinaryObjectScanner/FileType/GCF.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using BinaryObjectScanner.Interfaces; @@ -32,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAll(gcf, outDir); + gcf.ExtractAll(outDir); return true; } @@ -42,110 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all files from the GCF to an output directory - /// - /// Output directory to write to - /// True if all files extracted, false otherwise - public static bool ExtractAll(SabreTools.Serialization.Wrappers.GCF item, string outputDirectory) - { - // If we have no files - if (item.Files == null || item.Files.Length == 0) - return false; - - // Loop through and extract all files to the output - bool allExtracted = true; - for (int i = 0; i < item.Files.Length; i++) - { - allExtracted &= ExtractFile(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a file from the GCF to an output directory by index - /// - /// File index to extract - /// Output directory to write to - /// True if the file extracted, false otherwise - public static bool ExtractFile(SabreTools.Serialization.Wrappers.GCF item, int index, string outputDirectory) - { - // If we have no files - if (item.Files == null || item.Files.Length == 0 || item.DataBlockOffsets == null) - return false; - - // If the files index is invalid - if (index < 0 || index >= item.Files.Length) - return false; - - // Get the file - var file = item.Files[index]; - if (file?.BlockEntries == null || file.Size == 0) - return false; - - // If the file is encrypted -- TODO: Revisit later - if (file.Encrypted) - return false; - - // Get all data block offsets needed for extraction - var dataBlockOffsets = new List(); - for (int i = 0; i < file.BlockEntries.Length; i++) - { - var blockEntry = file.BlockEntries[i]; - if (blockEntry == null) - continue; - - uint dataBlockIndex = blockEntry.FirstDataBlockIndex; - long blockEntrySize = blockEntry.FileDataSize; - while (blockEntrySize > 0) - { - long dataBlockOffset = item.DataBlockOffsets[dataBlockIndex++]; - dataBlockOffsets.Add(dataBlockOffset); - blockEntrySize -= item.Model.DataBlockHeader?.BlockSize ?? 0; - } - } - - // Create the filename - var filename = file.Path; - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - - // Now read the data sequentially and write out while we have data left - long fileSize = file.Size; - for (int i = 0; i < dataBlockOffsets.Count; i++) - { - int readSize = (int)Math.Min(item.Model.DataBlockHeader?.BlockSize ?? 0, fileSize); - var data = item.ReadFromDataSource((int)dataBlockOffsets[i], readSize); - if (data == null) - return false; - - fs.Write(data, 0, data.Length); - } - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/PAK.cs b/BinaryObjectScanner/FileType/PAK.cs index 12d78d3b..6235f736 100644 --- a/BinaryObjectScanner/FileType/PAK.cs +++ b/BinaryObjectScanner/FileType/PAK.cs @@ -31,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAll(pak, outDir); + pak.ExtractAll(outDir); return true; } @@ -41,82 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all files from the PAK to an output directory - /// - /// Output directory to write to - /// True if all files extracted, false otherwise - public static bool ExtractAll(SabreTools.Serialization.Wrappers.PAK item, string outputDirectory) - { - // If we have no directory items - if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0) - return false; - - // Loop through and extract all files to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.DirectoryItems.Length; i++) - { - allExtracted &= ExtractFile(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a file from the PAK to an output directory by index - /// - /// File index to extract - /// Output directory to write to - /// True if the file extracted, false otherwise - public static bool ExtractFile(SabreTools.Serialization.Wrappers.PAK item, int index, string outputDirectory) - { - // If we have no directory items - if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0) - return false; - - // If the directory item index is invalid - if (index < 0 || index >= item.Model.DirectoryItems.Length) - return false; - - // Get the directory item - var directoryItem = item.Model.DirectoryItems[index]; - if (directoryItem == null) - return false; - - // Read the item data - var data = item.ReadFromDataSource((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength); - if (data == null) - return false; - - // Create the filename - var filename = directoryItem.ItemName; - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/PFF.cs b/BinaryObjectScanner/FileType/PFF.cs index f94711d1..ba6d6956 100644 --- a/BinaryObjectScanner/FileType/PFF.cs +++ b/BinaryObjectScanner/FileType/PFF.cs @@ -31,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Extract all files Directory.CreateDirectory(outDir); - ExtractAll(pff, outDir); + pff.ExtractAll(outDir); return true; } @@ -41,77 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all segments from the PFF to an output directory - /// - /// Output directory to write to - /// True if all segments extracted, false otherwise - public static bool ExtractAll(SabreTools.Serialization.Wrappers.PFF item, string outputDirectory) - { - // If we have no segments - if (item.Model.Segments == null || item.Model.Segments.Length == 0) - return false; - - // Loop through and extract all files to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.Segments.Length; i++) - { - allExtracted &= ExtractSegment(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a segment from the PFF to an output directory by index - /// - /// Segment index to extract - /// Output directory to write to - /// True if the segment extracted, false otherwise - public static bool ExtractSegment(SabreTools.Serialization.Wrappers.PFF item, int index, string outputDirectory) - { - // If we have no segments - if (item.Model.Header?.NumberOfFiles == null || item.Model.Header.NumberOfFiles == 0 || item.Model.Segments == null || item.Model.Segments.Length == 0) - return false; - - // If we have an invalid index - if (index < 0 || index >= item.Model.Segments.Length) - return false; - - // Get the segment information - var file = item.Model.Segments[index]; - if (file == null) - return false; - - // Get the read index and length - int offset = (int)file.FileLocation; - int size = (int)file.FileSize; - - try - { - // Ensure the output directory exists - Directory.CreateDirectory(outputDirectory); - - // Create the output path - string filePath = Path.Combine(outputDirectory, file.FileName ?? $"file{index}"); - using (FileStream fs = File.OpenWrite(filePath)) - { - // Read the data block - var data = item.ReadFromDataSource(offset, size); - if (data == null) - return false; - - // Write the data -- TODO: Compressed data? - fs.Write(data, 0, size); - } - - return true; - } - catch - { - return false; - } - } } } diff --git a/BinaryObjectScanner/FileType/SGA.cs b/BinaryObjectScanner/FileType/SGA.cs index 22fbf8ee..20d86df4 100644 --- a/BinaryObjectScanner/FileType/SGA.cs +++ b/BinaryObjectScanner/FileType/SGA.cs @@ -52,22 +52,13 @@ namespace BinaryObjectScanner.FileType public static bool ExtractAll(SabreTools.Serialization.Wrappers.SGA item, string outputDirectory) { // Get the file count - int filesLength = item.Model.Directory switch - { - SabreTools.Models.SGA.Directory4 d4 => d4.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory5 d5 => d5.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory6 d6 => d6.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory7 d7 => d7.Files?.Length ?? 0, - _ => 0, - }; - - // If we have no files - if (filesLength == 0) + int fileCount = item.FileCount; + if (fileCount == 0) return false; // Loop through and extract all files to the output bool allExtracted = true; - for (int i = 0; i < filesLength; i++) + for (int i = 0; i < fileCount; i++) { allExtracted &= ExtractFile(item, i, outputDirectory); } @@ -84,45 +75,16 @@ namespace BinaryObjectScanner.FileType public static bool ExtractFile(SabreTools.Serialization.Wrappers.SGA item, int index, string outputDirectory) { // Get the file count - int filesLength = item.Model.Directory switch - { - SabreTools.Models.SGA.Directory4 d4 => filesLength = d4.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory5 d5 => filesLength = d5.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory6 d6 => filesLength = d6.Files?.Length ?? 0, - SabreTools.Models.SGA.Directory7 d7 => filesLength = d7.Files?.Length ?? 0, - _ => 0, - }; - - // If we have no files - if (filesLength == 0) + int fileCount = item.FileCount; + if (fileCount == 0) return false; // If the files index is invalid - if (index < 0 || index >= filesLength) - return false; - - // Get the files - object? file = item.Model.Directory switch - { - SabreTools.Models.SGA.Directory4 d4 => d4.Files![index], - SabreTools.Models.SGA.Directory5 d5 => d5.Files![index], - SabreTools.Models.SGA.Directory6 d6 => d6.Files![index], - SabreTools.Models.SGA.Directory7 d7 => d7.Files![index], - _ => null, - }; - - // If the file is invalid - if (file == null) + if (index < 0 || index >= fileCount) return false; // Create the filename - var filename = file switch - { - SabreTools.Models.SGA.File4 f4 => f4.Name, - _ => null, - }; - - // If the filename is invalid + var filename = item.GetFileName(index); if (filename == null) return false; @@ -130,26 +92,9 @@ namespace BinaryObjectScanner.FileType var parentNames = new List { filename }; // Get the parent directory - var folder = item.Model.Directory switch - { - SabreTools.Models.SGA.Directory4 d4 => Array.Find(d4.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex), - SabreTools.Models.SGA.Directory5 d5 => Array.Find(d5.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex), - SabreTools.Models.SGA.Directory6 d6 => Array.Find(d6.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex), - SabreTools.Models.SGA.Directory7 d7 => Array.Find(d7.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex), - _ => default(object), - }; - - // If we have a parent folder - if (folder != null) - { - string folderName = folder switch - { - SabreTools.Models.SGA.Folder4 f4 => f4.Name ?? string.Empty, - SabreTools.Models.SGA.Folder5 f5 => f5.Name ?? string.Empty, - _ => string.Empty, - }; + string? folderName = item.GetParentName(index); + if (folderName != null) parentNames.Add(folderName); - } // TODO: Should the section name/alias be used in the path as well? @@ -165,37 +110,15 @@ namespace BinaryObjectScanner.FileType filename = Path.Combine([.. parentNames]); #endif - // Get the file offset - long fileOffset = file switch - { - SabreTools.Models.SGA.File4 f4 => f4.Offset, - _ => -1, - }; - - // Adjust the file offset - fileOffset += item.Model.Header switch - { - SabreTools.Models.SGA.Header4 h4 => h4.FileDataOffset, - SabreTools.Models.SGA.Header6 h6 => h6.FileDataOffset, - _ => -1, - }; - - // If the offset is invalid + // Get and adjust the file offset + long fileOffset = item.GetFileOffset(index); + fileOffset += item.FileDataOffset; if (fileOffset < 0) return false; // Get the file sizes - long fileSize, outputFileSize; - switch (file) - { - case SabreTools.Models.SGA.File4 f4: - fileSize = f4.SizeOnDisk; - outputFileSize = f4.Size; - break; - - default: - return false; - } + long fileSize = item.GetCompressedSize(index); + long outputFileSize = item.GetUncompressedSize(index); // Read the compressed data directly var compressedData = item.ReadFromDataSource((int)fileOffset, (int)fileSize); diff --git a/BinaryObjectScanner/FileType/VBSP.cs b/BinaryObjectScanner/FileType/VBSP.cs index 520dde12..c117020f 100644 --- a/BinaryObjectScanner/FileType/VBSP.cs +++ b/BinaryObjectScanner/FileType/VBSP.cs @@ -1,7 +1,6 @@ using System; using System.IO; using BinaryObjectScanner.Interfaces; -using SabreTools.Models.BSP; namespace BinaryObjectScanner.FileType { @@ -34,7 +33,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAllLumps(vbsp, outDir); + vbsp.ExtractAllLumps(outDir); return true; } @@ -44,91 +43,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all lumps from the VBSP to an output directory - /// - /// Output directory to write to - /// True if all lumps extracted, false otherwise - public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.VBSP item, string outputDirectory) - { - // If we have no lumps - if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0) - return false; - - // Loop through and extract all lumps to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.Header.Lumps.Length; i++) - { - allExtracted &= ExtractLump(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a lump from the VBSP to an output directory by index - /// - /// Lump index to extract - /// Output directory to write to - /// True if the lump extracted, false otherwise - public static bool ExtractLump(SabreTools.Serialization.Wrappers.VBSP item, int index, string outputDirectory) - { - // If we have no lumps - if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0) - return false; - - // If the lumps index is invalid - if (index < 0 || index >= item.Model.Header.Lumps.Length) - return false; - - // Get the lump - var lump = item.Model.Header.Lumps[index]; - if (lump == null) - return false; - - // Read the data - var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length); - if (data == null) - return false; - - // Create the filename - string filename = $"lump_{index}.bin"; - switch ((LumpType)index) - { - case LumpType.LUMP_ENTITIES: - filename = "entities.ent"; - break; - case LumpType.LUMP_PAKFILE: - filename = "pakfile.zip"; - break; - } - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/VPK.cs b/BinaryObjectScanner/FileType/VPK.cs index 2ab2ab43..1b7b9d17 100644 --- a/BinaryObjectScanner/FileType/VPK.cs +++ b/BinaryObjectScanner/FileType/VPK.cs @@ -1,7 +1,6 @@ using System; using System.IO; using BinaryObjectScanner.Interfaces; -using SabreTools.IO.Extensions; namespace BinaryObjectScanner.FileType { @@ -32,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAll(vpk, outDir); + vpk.ExtractAll(outDir); return true; } @@ -42,138 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all files from the VPK to an output directory - /// - /// Output directory to write to - /// True if all files extracted, false otherwise - public static bool ExtractAll(SabreTools.Serialization.Wrappers.VPK item, string outputDirectory) - { - // If we have no directory items - if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0) - return false; - - // Loop through and extract all files to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.DirectoryItems.Length; i++) - { - allExtracted &= ExtractFile(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a file from the VPK to an output directory by index - /// - /// File index to extract - /// Output directory to write to - /// True if the file extracted, false otherwise - public static bool ExtractFile(SabreTools.Serialization.Wrappers.VPK item, int index, string outputDirectory) - { - // If we have no directory items - if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0) - return false; - - // If the directory item index is invalid - if (index < 0 || index >= item.Model.DirectoryItems.Length) - return false; - - // Get the directory item - var directoryItem = item.Model.DirectoryItems[index]; - if (directoryItem?.DirectoryEntry == null) - return false; - - // If we have an item with no archive - var data = new byte[0]; - if (directoryItem.DirectoryEntry.ArchiveIndex == SabreTools.Models.VPK.Constants.HL_VPK_NO_ARCHIVE) - { - if (directoryItem.PreloadData == null) - return false; - - data = directoryItem.PreloadData; - } - else - { - // If we have invalid archives - if (item.ArchiveFilenames == null || item.ArchiveFilenames.Length == 0) - return false; - - // If we have an invalid index - if (directoryItem.DirectoryEntry.ArchiveIndex < 0 || directoryItem.DirectoryEntry.ArchiveIndex >= item.ArchiveFilenames.Length) - return false; - - // Get the archive filename - string archiveFileName = item.ArchiveFilenames[directoryItem.DirectoryEntry.ArchiveIndex]; - if (string.IsNullOrEmpty(archiveFileName)) - return false; - - // If the archive doesn't exist - if (!File.Exists(archiveFileName)) - return false; - - // Try to open the archive - var archiveStream = default(Stream); - try - { - // Open the archive - archiveStream = File.Open(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - - // Seek to the data - archiveStream.Seek(directoryItem.DirectoryEntry.EntryOffset, SeekOrigin.Begin); - - // Read the directory item bytes - data = archiveStream.ReadBytes((int)directoryItem.DirectoryEntry.EntryLength); - } - catch - { - return false; - } - finally - { - archiveStream?.Close(); - } - - // If we have preload data, prepend it - if (data != null && directoryItem.PreloadData != null) - data = [.. directoryItem.PreloadData, .. data]; - } - - // If there is nothing to write out - if (data == null) - return false; - - // Create the filename - string filename = $"{directoryItem.Name}.{directoryItem.Extension}"; - if (!string.IsNullOrEmpty(directoryItem.Path)) - filename = Path.Combine(directoryItem.Path, filename); - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/WAD3.cs b/BinaryObjectScanner/FileType/WAD3.cs index 916f7f3f..18d0abb5 100644 --- a/BinaryObjectScanner/FileType/WAD3.cs +++ b/BinaryObjectScanner/FileType/WAD3.cs @@ -31,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAllLumps(wad, outDir); + wad.ExtractAllLumps(outDir); return true; } @@ -41,82 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all lumps from the WAD3 to an output directory - /// - /// Output directory to write to - /// True if all lumps extracted, false otherwise - public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.WAD3 item, string outputDirectory) - { - // If we have no lumps - if (item.Model.DirEntries == null || item.Model.DirEntries.Length == 0) - return false; - - // Loop through and extract all lumps to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.DirEntries.Length; i++) - { - allExtracted &= ExtractLump(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a lump from the WAD3 to an output directory by index - /// - /// Lump index to extract - /// Output directory to write to - /// True if the lump extracted, false otherwise - public static bool ExtractLump(SabreTools.Serialization.Wrappers.WAD3 item, int index, string outputDirectory) - { - // If we have no lumps - if (item.Model.DirEntries == null || item.Model.DirEntries.Length == 0) - return false; - - // If the lumps index is invalid - if (index < 0 || index >= item.Model.DirEntries.Length) - return false; - - // Get the lump - var lump = item.Model.DirEntries[index]; - if (lump == null) - return false; - - // Read the data -- TODO: Handle uncompressed lumps (see BSP.ExtractTexture) - var data = item.ReadFromDataSource((int)lump.Offset, (int)lump.Length); - if (data == null) - return false; - - // Create the filename - string filename = $"{lump.Name}.lmp"; - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } } diff --git a/BinaryObjectScanner/FileType/XZP.cs b/BinaryObjectScanner/FileType/XZP.cs index d1a174a2..bda2d09f 100644 --- a/BinaryObjectScanner/FileType/XZP.cs +++ b/BinaryObjectScanner/FileType/XZP.cs @@ -31,7 +31,7 @@ namespace BinaryObjectScanner.FileType // Loop through and extract all files Directory.CreateDirectory(outDir); - ExtractAll(xzp, outDir); + xzp.ExtractAll(outDir); return true; } @@ -41,91 +41,5 @@ namespace BinaryObjectScanner.FileType return false; } } - - /// - /// Extract all files from the XZP to an output directory - /// - /// Output directory to write to - /// True if all files extracted, false otherwise - public static bool ExtractAll(SabreTools.Serialization.Wrappers.XZP item, string outputDirectory) - { - // If we have no directory entries - if (item.Model.DirectoryEntries == null || item.Model.DirectoryEntries.Length == 0) - return false; - - // Loop through and extract all files to the output - bool allExtracted = true; - for (int i = 0; i < item.Model.DirectoryEntries.Length; i++) - { - allExtracted &= ExtractFile(item, i, outputDirectory); - } - - return allExtracted; - } - - /// - /// Extract a file from the XZP to an output directory by index - /// - /// File index to extract - /// Output directory to write to - /// True if the file extracted, false otherwise - public static bool ExtractFile(SabreTools.Serialization.Wrappers.XZP item, int index, string outputDirectory) - { - // If we have no directory entries - if (item.Model.DirectoryEntries == null || item.Model.DirectoryEntries.Length == 0) - return false; - - // If we have no directory items - if (item.Model.DirectoryItems == null || item.Model.DirectoryItems.Length == 0) - return false; - - // If the directory entry index is invalid - if (index < 0 || index >= item.Model.DirectoryEntries.Length) - return false; - - // Get the directory entry - var directoryEntry = item.Model.DirectoryEntries[index]; - if (directoryEntry == null) - return false; - - // Get the associated directory item - var directoryItem = Array.Find(item.Model.DirectoryItems, di => di?.FileNameCRC == directoryEntry.FileNameCRC); - if (directoryItem == null) - return false; - - // Load the item data - var data = item.ReadFromDataSource((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength); - if (data == null) - return false; - - // Create the filename - var filename = directoryItem.Name; - - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; - - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); - - // Ensure the output directory is created - var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) - Directory.CreateDirectory(directoryName); - - // Try to write the data - try - { - // Open the output file for writing - using Stream fs = File.OpenWrite(filename); - fs.Write(data, 0, data.Length); - } - catch - { - return false; - } - - return true; - } } }