using System.Collections.Generic; using System.IO; using System.Linq; namespace com.clusterrr.Famicom.Containers { /// /// File container for FDS games, disk sides collection /// public class FdsFile { IList sides; /// /// Disk Side Images /// public IList Sides { get => sides; set => sides = value ?? new List(); } /// /// Constructor to create empty FdsFile object /// public FdsFile() { sides = new List(); } /// /// Create FdsFile object from the specified .nes file /// /// Path to the .fds file public FdsFile(string filename) : this(File.ReadAllBytes(filename)) { } /// /// Create FdsFile object from raw .fds file data /// /// public FdsFile(byte[] data) : this() { if (data[0] == (byte)'F' && data[1] == (byte)'D' && data[2] == (byte)'S' && data[3] == 0x1A) data = data.Skip(16).ToArray(); // skip header if (data.Length % 65500 != 0) throw new InvalidDataException("Invalid FDS image: the size must be divisible by 65500"); for (int i = 0; i < data.Length; i += 65500) { var sideData = data.Skip(i).Take(66500).ToArray(); sides.Add(FdsDiskSide.FromBytes(sideData)); } } /// /// Create FdsFile object from set of FdsDiskSide objects /// /// public FdsFile(IEnumerable sides) { this.sides = new List(sides); } /// /// Create FdsFile object from raw .fds file contents /// /// /// FdsFile object public static FdsFile FromBytes(byte[] data) =>new FdsFile(data); /// /// Create FileFile object from the specified .nes file /// /// Path to the .fds file /// FdsFile object public static FdsFile FromFile(string filename) => new FdsFile(filename); /// /// Returns .fds file contents /// /// Option to add .fds file header (ignored by most emulators) /// FDS file contents public byte[] ToBytes(bool useHeader = false) { var data = sides.SelectMany(s => s.ToBytes()); if (useHeader) { var header = new byte[16]; header[0] = (byte)'F'; header[1] = (byte)'D'; header[2] = (byte)'S'; header[3] = 0x1A; header[4] = (byte)sides.Count(); data = Enumerable.Concat(header, data); } return data.ToArray(); } /// /// Save as .fds file /// /// Target filename /// Option to add .fds file header (ignored by most emulators) public void Save(string filename, bool useHeader = false) => File.WriteAllBytes(filename, ToBytes(useHeader)); } }