From 650402df39f166f5809f8d3de915dac2a4249fc9 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 14 Apr 2026 12:17:42 -0400 Subject: [PATCH] Add FDS image writer --- .../FDSTests.cs | 24 ++++ SabreTools.Serialization.Writers/FDS.cs | 103 ++++++++++++++++++ SabreTools.Wrappers/FDS.Extraction.cs | 7 +- SabreTools.Wrappers/FDS.Writing.cs | 15 +-- 4 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 SabreTools.Serialization.Writers.Test/FDSTests.cs create mode 100644 SabreTools.Serialization.Writers/FDS.cs diff --git a/SabreTools.Serialization.Writers.Test/FDSTests.cs b/SabreTools.Serialization.Writers.Test/FDSTests.cs new file mode 100644 index 00000000..7b4be00f --- /dev/null +++ b/SabreTools.Serialization.Writers.Test/FDSTests.cs @@ -0,0 +1,24 @@ +using System.IO; +using Xunit; + +namespace SabreTools.Serialization.Writers.Test +{ + public class FDSTests + { + [Fact] + public void SerializeArray_Null_Null() + { + var serializer = new FDS(); + byte[]? actual = serializer.SerializeArray(null); + Assert.Null(actual); + } + + [Fact] + public void SerializeStream_Null_Null() + { + var serializer = new FDS(); + Stream? actual = serializer.SerializeStream(null); + Assert.Null(actual); + } + } +} diff --git a/SabreTools.Serialization.Writers/FDS.cs b/SabreTools.Serialization.Writers/FDS.cs new file mode 100644 index 00000000..8a61cf88 --- /dev/null +++ b/SabreTools.Serialization.Writers/FDS.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using SabreTools.Data.Models.NES; +using SabreTools.IO.Extensions; +using SabreTools.Numerics.Extensions; + +namespace SabreTools.Serialization.Writers +{ + public class FDS : BaseBinaryWriter + { + /// + public override Stream? SerializeStream(Data.Models.NES.FDS? obj) + { + // If the metadata file is null + if (obj is null) + return null; + + // Setup the writer and output + var stream = new MemoryStream(); + + // Write header + if (!WriteHeader(obj.Header, stream)) + return null; + + // Write data + if (!WriteRom(obj.Data, stream)) + return null; + + // Return the stream + stream.SeekIfPossible(0, SeekOrigin.Begin); + return stream; + } + + /// + /// Write header data to the stream + /// + /// Stream to write to + /// True if the writing was successful, false otherwise + public bool WriteHeader(FDSHeader? obj, Stream stream) + { + if (obj is null) + { + if (Debug) Console.WriteLine("Header was invalid!"); + return false; + } + + // Try to write the data + try + { + if (Debug) Console.WriteLine("Attempting to write header data"); + + // Bytes 0-3 + stream.Write(obj.IdentificationString); + stream.Flush(); + + // Byte 4 + stream.Write(obj.DiskSides); + stream.Flush(); + + // Byte 5-15 + stream.Write(obj.Padding); + stream.Flush(); + + // Header extracted + return true; + } + catch (Exception ex) + { + if (Debug) Console.Error.WriteLine(ex); + return false; + } + } + + /// + /// Write rom data to the stream + /// + /// Stream to write to + /// True if the writing was successful, false otherwise + public bool WriteRom(byte[]? obj, Stream stream) + { + if (obj is null || obj.Length == 0) + { + if (Debug) Console.WriteLine("ROM data was invalid!"); + return false; + } + + // Try to write the data + try + { + if (Debug) Console.WriteLine("Attempting to write ROM data"); + + stream.Write(obj, 0, obj.Length); + stream.Flush(); + return true; + } + catch (Exception ex) + { + if (Debug) Console.Error.WriteLine(ex); + return false; + } + } + } +} diff --git a/SabreTools.Wrappers/FDS.Extraction.cs b/SabreTools.Wrappers/FDS.Extraction.cs index 74c6e972..22c3ca97 100644 --- a/SabreTools.Wrappers/FDS.Extraction.cs +++ b/SabreTools.Wrappers/FDS.Extraction.cs @@ -15,6 +15,9 @@ namespace SabreTools.Wrappers : Path.GetFileNameWithoutExtension(Filename); string basePath = Path.Combine(outputDirectory, baseFilename); + // Create the writer + var writer = new Serialization.Writers.FDS { Debug = includeDebug }; + // Check if any data was extracted successfully bool success = false; @@ -28,7 +31,7 @@ namespace SabreTools.Wrappers try { using var fs = File.Open(headerPath, FileMode.Create, FileAccess.Write, FileShare.None); - success |= WriteHeader(fs, includeDebug); + success |= writer.WriteHeader(Header, fs); } catch (Exception ex) { @@ -46,7 +49,7 @@ namespace SabreTools.Wrappers try { using var fs = File.Open(romPath, FileMode.Create, FileAccess.Write, FileShare.None); - success |= WriteRom(fs, includeDebug); + success |= writer.WriteRom(Model.Data, fs); } catch (Exception ex) { diff --git a/SabreTools.Wrappers/FDS.Writing.cs b/SabreTools.Wrappers/FDS.Writing.cs index 8244b62c..6d44f1c2 100644 --- a/SabreTools.Wrappers/FDS.Writing.cs +++ b/SabreTools.Wrappers/FDS.Writing.cs @@ -25,18 +25,9 @@ namespace SabreTools.Wrappers return false; } - // Open the output file for writing - using var fs = File.Open(outputPath, FileMode.Create, FileAccess.Write, FileShare.None); - - // Header data - if (!WriteHeader(fs, includeDebug)) - return false; - - // ROM data - if (!WriteRom(fs, includeDebug)) - return false; - - return true; + // Create and use the writer + var writer = new Serialization.Writers.FDS { Debug = includeDebug }; + return writer.SerializeFile(Model, outputPath); } ///