diff --git a/SabreTools.Models/DosCenter/DosCenter.cs b/SabreTools.Models/DosCenter/DosCenter.cs
index 9fb3fda2..8368d8a7 100644
--- a/SabreTools.Models/DosCenter/DosCenter.cs
+++ b/SabreTools.Models/DosCenter/DosCenter.cs
@@ -27,7 +27,7 @@ namespace SabreTools.Models.DosCenter
#region DO NOT USE IN PRODUCTION
/// Should be empty
- public string[] ADDITIONAL_ELEMENTS { get; set; }
+ public string[]? ADDITIONAL_ELEMENTS { get; set; }
#endregion
}
diff --git a/SabreTools.Models/Hashfile/Hashfile.cs b/SabreTools.Models/Hashfile/Hashfile.cs
index 3dd5f4e2..ad694120 100644
--- a/SabreTools.Models/Hashfile/Hashfile.cs
+++ b/SabreTools.Models/Hashfile/Hashfile.cs
@@ -16,5 +16,12 @@ namespace SabreTools.Models.Hashfile
public SHA512[]? SHA512 { get; set; }
public SpamSum[]? SpamSum { get; set; }
+
+ #region DO NOT USE IN PRODUCTION
+
+ /// Should be empty
+ public string[]? ADDITIONAL_ELEMENTS { get; set; }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/SabreTools.Serialization/Hashfile.cs b/SabreTools.Serialization/Hashfile.cs
new file mode 100644
index 00000000..a26cad38
--- /dev/null
+++ b/SabreTools.Serialization/Hashfile.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using SabreTools.Core;
+
+namespace SabreTools.Serialization
+{
+ ///
+ /// Serializer for hashfile variants
+ ///
+ public class Hashfile
+ {
+ ///
+ /// Deserializes a hashfile variant to the defined type
+ ///
+ /// Path to the file to deserialize
+ /// Hash corresponding to the hashfile variant
+ /// Deserialized data on success, null on failure
+ public static Models.Hashfile.Hashfile? Deserialize(string path, Hash hash)
+ {
+ try
+ {
+ using var stream = PathProcessor.OpenStream(path);
+ return Deserialize(stream, hash);
+ }
+ catch
+ {
+ // TODO: Handle logging the exception
+ return default;
+ }
+ }
+
+ ///
+ /// Deserializes a hashfile variant in a stream to the defined type
+ ///
+ /// Stream to deserialize
+ /// Hash corresponding to the hashfile variant
+ /// Deserialized data on success, null on failure
+ public static Models.Hashfile.Hashfile? Deserialize(Stream? stream, Hash hash)
+ {
+ try
+ {
+ // If the stream is null
+ if (stream == null)
+ return default;
+
+ // Setup the reader and output
+ var reader = new StreamReader(stream);
+ var dat = new Models.Hashfile.Hashfile();
+ var additional = new List();
+
+ // Loop through the rows and parse out values
+ var hashes = new List