// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Helpers.cs // Author(s) : Rebecca Wallander // // Component : Disk image plugins. // // --[ Description ] ---------------------------------------------------------- // // Contains helpers for A2R flux images. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2023 Rebecca Wallander // ****************************************************************************/ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Aaru.CommonTypes; namespace Aaru.Images; [SuppressMessage("ReSharper", "UnusedType.Global")] public sealed partial class A2R { /// /// Takes a Head, Track and Sub-Track representation, as well as the MediaType, /// and converts it to the Track representation used by A2R. /// /// The head number /// The track number /// The sub-track number /// The media type of the image /// A2R format location static long HeadTrackSubToA2RLocation(uint head, ushort track, byte subTrack, MediaType mediaType) { if(mediaType == MediaType.Apple32SS) return head + track * 4 + subTrack; return head + track * 2; } /// /// Takes a Head, Track and Sub-Track representation, as well as the A2rDriveType, /// and converts it to the Track representation used by A2R. /// /// The head number /// The track number /// The sub-track number /// The drive type enum of the A2R image /// A2R format location static long HeadTrackSubToA2RLocation(uint head, ushort track, byte subTrack, A2rDriveType driveType) { if(driveType == A2rDriveType.SS_525_40trk_quarterStep) return head + track * 4 + subTrack; return head + track * 2; } /// /// Takes an A2R location and a MediaType, and converts it to a Head, Track and Sub-Track representation /// used by the internal representation. The MediaType is needed because the track location is different /// for different types of media sources. /// /// A2R format location /// /// The head number /// The track number /// The sub-track number static void A2RLocationToHeadTrackSub(uint location, MediaType mediaType, out uint head, out ushort track, out byte subTrack) { if(mediaType == MediaType.Apple32SS) { head = 0; track = (ushort)(location / 4); subTrack = (byte)(location % 4); return; } head = location % 2; track = (ushort)((location - head) / 2); subTrack = 0; } /// /// Takes a single number flux (uint length) and converts it to a flux in the /// internal representation format (byte length) /// /// The uint flux representation /// The byte[] flux representation static byte[] UInt32ToFluxRepresentation(uint ticks) { uint over = ticks / 255; if(over == 0) { return new[] { (byte)ticks }; } var expanded = new byte[over + 1]; Array.Fill(expanded, (byte)255, 0, (int)over); expanded[^1] = (byte)(ticks % 255); return expanded; } /// /// Takes a flux representation in the internal format (byte length) and converts it to /// an array of single number fluxes (uint length) /// /// The byte[] flux representation /// The uint flux representation static List FluxRepresentationsToUInt32List(IEnumerable flux) { List scpData = new(); uint tick = 0; foreach(byte b in flux) { if(b == 255) tick += 255; else { tick += b; scpData.Add(tick); tick = 0; } } return scpData; } /// /// A2R has two types of flux capture types; "timing" and "xtiming". The only difference is the length of the /// capture, with "timing" being about 1¼ revolutions. This function returns true if the flux buffer is "timing" /// and false otherwise. /// /// The resolution of the flux capture /// The flux data /// true if "timing", false if "xtiming" static bool IsCaptureTypeTiming(ulong resolution, byte[] buffer) => // TODO: This is only accurate for 300rpm buffer.Select(static x => (int)x).Sum() * (long)resolution is > 230000000000 and < 270000000000; }