From b51879bbecdd30d4bd43c989edf797cdd4796815 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 14 Apr 2026 10:13:05 -0400 Subject: [PATCH] Add A78 cart writing --- .../Atari7800Cart.Extraction.cs | 88 +-------- SabreTools.Wrappers/Atari7800Cart.Writing.cs | 168 ++++++++++++++++++ 2 files changed, 170 insertions(+), 86 deletions(-) create mode 100644 SabreTools.Wrappers/Atari7800Cart.Writing.cs diff --git a/SabreTools.Wrappers/Atari7800Cart.Extraction.cs b/SabreTools.Wrappers/Atari7800Cart.Extraction.cs index ee03c284..bd85a0f1 100644 --- a/SabreTools.Wrappers/Atari7800Cart.Extraction.cs +++ b/SabreTools.Wrappers/Atari7800Cart.Extraction.cs @@ -1,7 +1,5 @@ using System; using System.IO; -using SabreTools.Data.Models.Atari7800; -using SabreTools.Numerics.Extensions; namespace SabreTools.Wrappers { @@ -28,85 +26,8 @@ namespace SabreTools.Wrappers // Try to write the data try { - // Open the output file for writing using var fs = File.Open(headerPath, FileMode.Create, FileAccess.Write, FileShare.None); - - // Byte 0 - fs.Write(Header.HeaderVersion); - fs.Flush(); - - // Bytes 1-16 - fs.Write(Header.MagicText); - fs.Flush(); - - // Bytes 17-48 - fs.Write(Header.CartTitle); - fs.Flush(); - - // Bytes 49-52 - fs.Write(Header.RomSizeWithoutHeader); - fs.Flush(); - - // Bytes 53-54 - fs.Write((ushort)Header.CartType); - fs.Flush(); - - // Bytes 55-56 - fs.Write((byte)Header.Controller1Type); - fs.Write((byte)Header.Controller2Type); - fs.Flush(); - - // Byte 57 - fs.Write((byte)Header.TVType); - fs.Flush(); - - // Byte 58 - fs.Write((byte)Header.SaveDevice); - fs.Flush(); - - // Bytes 59-62 - fs.Write(Header.Reserved); - fs.Flush(); - - // Byte 63 - fs.Write((byte)Header.SlotPassthroughDevice); - fs.Flush(); - - if (HeaderVersion >= 4) - { - // Byte 64 - fs.Write((byte)Header.Mapper); - fs.Flush(); - - // Byte 65 - fs.Write((byte)Header.MapperOptions); - fs.Flush(); - - // Byte 66-67 - fs.Write((ushort)Header.AudioDevice); - fs.Flush(); - - // Byte 68-69 - fs.Write((ushort)Header.Interrupt); - fs.Flush(); - - // Bytes 70-99 - fs.Write(Header.Padding); - fs.Flush(); - } - else - { - // Bytes 64-99 - fs.Write(Header.Padding); - fs.Flush(); - } - - // Bytes 100-127 - fs.Write(Header.EndMagicText); - fs.Flush(); - - // Header extracted - success = true; + success |= WriteHeader(fs, includeDebug); } catch (Exception ex) { @@ -123,13 +44,8 @@ namespace SabreTools.Wrappers // Try to write the data try { - // Open the output file for writing using var fs = File.Open(romPath, FileMode.Create, FileAccess.Write, FileShare.None); - fs.Write(Model.Data, 0, Model.Data.Length); - fs.Flush(); - - // ROM extracted - success = true; + success |= WriteRom(fs, includeDebug); } catch (Exception ex) { diff --git a/SabreTools.Wrappers/Atari7800Cart.Writing.cs b/SabreTools.Wrappers/Atari7800Cart.Writing.cs new file mode 100644 index 00000000..672d05dc --- /dev/null +++ b/SabreTools.Wrappers/Atari7800Cart.Writing.cs @@ -0,0 +1,168 @@ +using System; +using System.IO; +using SabreTools.Data.Models.Atari7800; +using SabreTools.Numerics.Extensions; + +namespace SabreTools.Wrappers +{ + public partial class Atari7800Cart : IWritable + { + /// + public bool Write(string outputDirectory, bool includeDebug) + { + // Get the base path + string outputFilename = Filename is null + ? Guid.NewGuid().ToString() + : Path.GetFileName(Filename); + outputFilename += ".a78"; + string outputPath = Path.Combine(outputDirectory, outputFilename); + + // Check for invalid data + if (Header is null || Model.Data is null || Model.Data.Length == 0) + { + if (includeDebug) Console.WriteLine("Model was invalid, cannot write!"); + 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; + } + + /// + /// Write header data to the stream + /// + /// Stream to write to + /// True to include debug data, false otherwise + /// True if the writing was successful, false otherwise + private bool WriteHeader(Stream stream, bool includeDebug) + { + if (includeDebug) Console.WriteLine("Attempting to extract header data"); + + if (Header is null) + { + if (includeDebug) Console.WriteLine("Header was invalid!"); + return false; + } + + // Try to write the data + try + { + // Byte 0 + stream.Write(Header.HeaderVersion); + stream.Flush(); + + // Bytes 1-16 + stream.Write(Header.MagicText); + stream.Flush(); + + // Bytes 17-48 + stream.Write(Header.CartTitle); + stream.Flush(); + + // Bytes 49-52 + stream.Write(Header.RomSizeWithoutHeader); + stream.Flush(); + + // Bytes 53-54 + stream.Write((ushort)Header.CartType); + stream.Flush(); + + // Bytes 55-56 + stream.Write((byte)Header.Controller1Type); + stream.Write((byte)Header.Controller2Type); + stream.Flush(); + + // Byte 57 + stream.Write((byte)Header.TVType); + stream.Flush(); + + // Byte 58 + stream.Write((byte)Header.SaveDevice); + stream.Flush(); + + // Bytes 59-62 + stream.Write(Header.Reserved); + stream.Flush(); + + // Byte 63 + stream.Write((byte)Header.SlotPassthroughDevice); + stream.Flush(); + + if (HeaderVersion >= 4) + { + // Byte 64 + stream.Write((byte)Header.Mapper); + stream.Flush(); + + // Byte 65 + stream.Write((byte)Header.MapperOptions); + stream.Flush(); + + // Byte 66-67 + stream.Write((ushort)Header.AudioDevice); + stream.Flush(); + + // Byte 68-69 + stream.Write((ushort)Header.Interrupt); + stream.Flush(); + + // Bytes 70-99 + stream.Write(Header.Padding); + stream.Flush(); + } + else + { + // Bytes 64-99 + stream.Write(Header.Padding); + stream.Flush(); + } + + // Bytes 100-127 + stream.Write(Header.EndMagicText); + stream.Flush(); + + // Header extracted + return true; + } + catch (Exception ex) + { + if (includeDebug) Console.Error.WriteLine(ex); + return false; + } + } + + /// + /// Write rom data to the stream + /// + /// Stream to write to + /// True to include debug data, false otherwise + /// True if the writing was successful, false otherwise + private bool WriteRom(Stream stream, bool includeDebug) + { + if (includeDebug) Console.WriteLine("Attempting to extract ROM data"); + + // Try to write the data + try + { + stream.Write(Model.Data, 0, Model.Data.Length); + stream.Flush(); + return true; + } + catch (Exception ex) + { + if (includeDebug) Console.Error.WriteLine(ex); + return false; + } + } + } +}