diff --git a/SabreTools.Serialization/Wrappers/AACSMediaKeyBlock.cs b/SabreTools.Serialization/Wrappers/AACSMediaKeyBlock.cs
index 63438f7c..20607e73 100644
--- a/SabreTools.Serialization/Wrappers/AACSMediaKeyBlock.cs
+++ b/SabreTools.Serialization/Wrappers/AACSMediaKeyBlock.cs
@@ -12,6 +12,15 @@ namespace SabreTools.Serialization.Wrappers
#endregion
+ #region Extension Properties
+
+ ///
+ /// Media key block records
+ ///
+ public Record?[] Records => Model.Records ?? [];
+
+ #endregion
+
#region Constructors
///
diff --git a/SabreTools.Serialization/Wrappers/BDPlusSVM.cs b/SabreTools.Serialization/Wrappers/BDPlusSVM.cs
index 19de47d3..4d429f35 100644
--- a/SabreTools.Serialization/Wrappers/BDPlusSVM.cs
+++ b/SabreTools.Serialization/Wrappers/BDPlusSVM.cs
@@ -12,6 +12,15 @@ namespace SabreTools.Serialization.Wrappers
#endregion
+ #region Extension Properties
+
+ ///
+ /// Human-readable version of the date
+ ///
+ public string Date => $"{Model.Year:0000}-{Model.Month:00}-{Model.Day:00}";
+
+ #endregion
+
#region Constructors
///
diff --git a/SabreTools.Serialization/Wrappers/SGA.cs b/SabreTools.Serialization/Wrappers/SGA.cs
index c41e75db..4b227783 100644
--- a/SabreTools.Serialization/Wrappers/SGA.cs
+++ b/SabreTools.Serialization/Wrappers/SGA.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
namespace SabreTools.Serialization.Wrappers
@@ -11,6 +12,49 @@ namespace SabreTools.Serialization.Wrappers
#endregion
+ #region Extension Properties
+
+ ///
+ /// Directory data
+ ///
+ public Models.SGA.Directory? Directory => Model.Directory;
+
+ ///
+ /// Number of files in the directory
+ ///
+ public int FileCount
+ {
+ get
+ {
+ return Directory switch
+ {
+ Models.SGA.Directory4 d4 => d4.Files?.Length ?? 0,
+ Models.SGA.Directory5 d5 => d5.Files?.Length ?? 0,
+ Models.SGA.Directory6 d6 => d6.Files?.Length ?? 0,
+ Models.SGA.Directory7 d7 => d7.Files?.Length ?? 0,
+ _ => 0,
+ };
+ }
+ }
+
+ ///
+ /// Offset to the file data
+ ///
+ public long FileDataOffset
+ {
+ get
+ {
+ return Model.Header switch
+ {
+ Models.SGA.Header4 h4 => h4.FileDataOffset,
+ Models.SGA.Header6 h6 => h6.FileDataOffset,
+ _ => -1,
+ };
+ }
+ }
+
+ #endregion
+
#region Constructors
///
@@ -74,5 +118,112 @@ namespace SabreTools.Serialization.Wrappers
}
#endregion
+
+ #region File
+
+ ///
+ /// Get the compressed size of a file
+ ///
+ public long GetCompressedSize(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return -1;
+
+ // Get the file and return the name
+ var file = GetFile(index);
+ return file?.Size ?? -1L;
+ }
+
+ ///
+ /// Get the uncompressed size of a file
+ ///
+ public long GetUncompressedSize(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return -1;
+
+ // Get the file and return the name
+ var file = GetFile(index);
+ return file?.SizeOnDisk ?? -1L;
+ }
+
+ ///
+ /// Get a file header from the archive
+ ///
+ public Models.SGA.File4? GetFile(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return null;
+
+ return Directory switch
+ {
+ Models.SGA.Directory4 d4 => d4.Files![index],
+ Models.SGA.Directory5 d5 => d5.Files![index],
+ Models.SGA.Directory6 d6 => d6.Files![index],
+ Models.SGA.Directory7 d7 => d7.Files![index],
+ _ => null,
+ };
+ }
+
+ ///
+ /// Get a file name from the archive
+ ///
+ public string? GetFileName(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return null;
+
+ // Get the file and return the name
+ var file = GetFile(index);
+ return file?.Name;
+ }
+
+ ///
+ /// Get a file offset from the archive
+ ///
+ public long GetFileOffset(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return -1;
+
+ // Get the file and return the name
+ var file = GetFile(index);
+ return file?.Offset ?? -1L;
+ }
+
+ ///
+ /// Get the parent name for a file
+ ///
+ public string? GetParentName(int index)
+ {
+ // If the index is invalid
+ if (index < 0 || index >= FileCount)
+ return null;
+
+ // Get the folder
+ object? folder = Directory switch
+ {
+ Models.SGA.Directory4 d4 => Array.Find(d4.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
+ Models.SGA.Directory5 d5 => Array.Find(d5.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
+ Models.SGA.Directory6 d6 => Array.Find(d6.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
+ Models.SGA.Directory7 d7 => Array.Find(d7.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
+ _ => default,
+ };
+
+ // Get the folder name
+ return folder switch
+ {
+ Models.SGA.Folder4 f4 => f4.Name,
+ Models.SGA.Folder5 f5 => f5.Name,
+ _ => null,
+ };
+ }
+
+ #endregion
}
}
\ No newline at end of file