diff --git a/SabreTools.Serialization/Wrappers/BFPK.cs b/SabreTools.Serialization/Wrappers/BFPK.cs
index 027a95f7..0bc7038a 100644
--- a/SabreTools.Serialization/Wrappers/BFPK.cs
+++ b/SabreTools.Serialization/Wrappers/BFPK.cs
@@ -15,9 +15,7 @@ namespace SabreTools.Serialization.Wrappers
#region Extension Properties
- ///
///
- ///
public FileEntry[] Files => Model.Files ?? [];
#endregion
diff --git a/SabreTools.Serialization/Wrappers/Quantum.cs b/SabreTools.Serialization/Wrappers/Quantum.cs
index e8c547f9..676a4d04 100644
--- a/SabreTools.Serialization/Wrappers/Quantum.cs
+++ b/SabreTools.Serialization/Wrappers/Quantum.cs
@@ -1,8 +1,9 @@
using System.IO;
+using SabreTools.Models.Quantum;
namespace SabreTools.Serialization.Wrappers
{
- public class Quantum : WrapperBase
+ public class Quantum : WrapperBase
{
#region Descriptive Properties
@@ -14,14 +15,14 @@ namespace SabreTools.Serialization.Wrappers
#region Constructors
///
- public Quantum(Models.Quantum.Archive? model, byte[]? data, int offset)
+ public Quantum(Archive? model, byte[]? data, int offset)
: base(model, data, offset)
{
// All logic is handled by the base class
}
///
- public Quantum(Models.Quantum.Archive? model, Stream? data)
+ public Quantum(Archive? model, Stream? data)
: base(model, data)
{
// All logic is handled by the base class
@@ -74,5 +75,130 @@ namespace SabreTools.Serialization.Wrappers
}
#endregion
+
+ #region Extension Properties
+
+ ///
+ public long CompressedDataOffset => Model.CompressedDataOffset;
+
+ ///
+ public ushort FileCount => Model.Header?.FileCount ?? 0;
+
+ ///
+ public FileDescriptor[] FileList => Model.FileList ?? [];
+
+ #endregion
+
+ #region Extraction
+
+ ///
+ /// Extract all files from the Quantum archive to an output directory
+ ///
+ /// Output directory to write to
+ /// True if all files extracted, false otherwise
+ public bool ExtractAll(string outputDirectory)
+ {
+ // If we have no files
+ if (FileList == null || FileList.Length == 0)
+ return false;
+
+ // Loop through and extract all files to the output
+ bool allExtracted = true;
+ for (int i = 0; i < FileList.Length; i++)
+ {
+ allExtracted &= ExtractFile(i, outputDirectory);
+ }
+
+ return allExtracted;
+ }
+
+ ///
+ /// Extract a file from the Quantum archive to an output directory by index
+ ///
+ /// File index to extract
+ /// Output directory to write to
+ /// True if the file extracted, false otherwise
+ public bool ExtractFile(int index, string outputDirectory)
+ {
+ // If we have no files
+ if (Model.Header == null || FileCount == 0 || FileList == null || FileList.Length == 0)
+ return false;
+
+ // If we have an invalid index
+ if (index < 0 || index >= FileList.Length)
+ return false;
+
+ // Get the file information
+ var fileDescriptor = FileList[index];
+
+ // Read the entire compressed data
+ int compressedDataOffset = (int)CompressedDataOffset;
+ int compressedDataLength = GetEndOfFile() - compressedDataOffset;
+ var compressedData = ReadFromDataSource(compressedDataOffset, compressedDataLength);
+
+ // TODO: Figure out decompression
+ // - Single-file archives seem to work
+ // - Single-file archives with files that span a window boundary seem to work
+ // - The first files in each archive seem to work
+ return false;
+
+ // // Setup the decompression state
+ // State state = new State();
+ // Decompressor.InitState(state, TableSize, CompressionFlags);
+
+ // // Decompress the entire array
+ // int decompressedDataLength = (int)FileList.Sum(fd => fd.ExpandedFileSize);
+ // byte[] decompressedData = new byte[decompressedDataLength];
+ // Decompressor.Decompress(state, compressedData.Length, compressedData, decompressedData.Length, decompressedData);
+
+ // // Read the data
+ // int offset = (int)FileList.Take(index).Sum(fd => fd.ExpandedFileSize);
+ // byte[] data = new byte[fileDescriptor.ExpandedFileSize];
+ // Array.Copy(decompressedData, offset, data, 0, data.Length);
+
+ // // Loop through all files before the current
+ // for (int i = 0; i < index; i++)
+ // {
+ // // Decompress the next block of data
+ // byte[] tempData = new byte[FileList[i].ExpandedFileSize];
+ // int lastRead = Decompressor.Decompress(state, compressedData.Length, compressedData, tempData.Length, tempData);
+ // compressedData = new ReadOnlySpan(compressedData, (lastRead), compressedData.Length - (lastRead)).ToArray();
+ // }
+
+ // // Read the data
+ // byte[] data = new byte[fileDescriptor.ExpandedFileSize];
+ // _ = Decompressor.Decompress(state, compressedData.Length, compressedData, data.Length, data);
+
+ // // Create the filename
+ // string filename = fileDescriptor.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
+ // Directory.CreateDirectory(Path.GetDirectoryName(filename));
+
+ // // 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;
+ }
+
+ #endregion
}
}
\ No newline at end of file