示例#1
0
文件: CRC16IBM.cs 项目: paulyc/Aaru
        public void Crc16IbmRandomData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            CRC16IBMContext.Data(data, out byte[] result);
            Assert.AreEqual(_expectedRandom, result);
        }
示例#2
0
        public void RandomData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            CRC16IBMContext.Data(data, out byte[] result);
            result.Should().BeEquivalentTo(_expectedRandom);
        }
示例#3
0
        public void EmptyInstance()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"), FileMode.Open,
                                    FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            IChecksum ctx = new CRC16IBMContext();

            ctx.Update(data);
            byte[] result = ctx.Final();
            result.Should().BeEquivalentTo(_expectedEmpty);
        }
示例#4
0
文件: CRC16IBM.cs 项目: paulyc/Aaru
        public void Crc16IbmRandomInstance()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            IChecksum ctx = new CRC16IBMContext();

            ctx.Update(data);
            byte[] result = ctx.Final();
            Assert.AreEqual(_expectedRandom, result);
        }
示例#5
0
        internal static List <ChecksumType> GetChecksums(byte[] data, EnableChecksum enabled = EnableChecksum.All)
        {
            IChecksum adler32CtxData = null;
            IChecksum crc16CtxData   = null;
            IChecksum crc32CtxData   = null;
            IChecksum crc64CtxData   = null;
            IChecksum md5CtxData     = null;
            IChecksum sha1CtxData    = null;
            IChecksum sha256CtxData  = null;
            IChecksum sha384CtxData  = null;
            IChecksum sha512CtxData  = null;
            IChecksum ssctxData      = null;
            IChecksum f16CtxData     = null;
            IChecksum f32CtxData     = null;

            var adlerThreadData   = new Thread(UpdateHash);
            var crc16ThreadData   = new Thread(UpdateHash);
            var crc32ThreadData   = new Thread(UpdateHash);
            var crc64ThreadData   = new Thread(UpdateHash);
            var md5ThreadData     = new Thread(UpdateHash);
            var sha1ThreadData    = new Thread(UpdateHash);
            var sha256ThreadData  = new Thread(UpdateHash);
            var sha384ThreadData  = new Thread(UpdateHash);
            var sha512ThreadData  = new Thread(UpdateHash);
            var spamsumThreadData = new Thread(UpdateHash);
            var f16ThreadData     = new Thread(UpdateHash);
            var f32ThreadData     = new Thread(UpdateHash);

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                adler32CtxData = new Adler32Context();

                var adlerPktData = new HashPacket
                {
                    Context = adler32CtxData,
                    Data    = data
                };

                adlerThreadData.Start(adlerPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                crc16CtxData = new CRC16IBMContext();

                var crc16PktData = new HashPacket
                {
                    Context = crc16CtxData,
                    Data    = data
                };

                crc16ThreadData.Start(crc16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                crc32CtxData = new Crc32Context();

                var crc32PktData = new HashPacket
                {
                    Context = crc32CtxData,
                    Data    = data
                };

                crc32ThreadData.Start(crc32PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                crc64CtxData = new Crc64Context();

                var crc64PktData = new HashPacket
                {
                    Context = crc64CtxData,
                    Data    = data
                };

                crc64ThreadData.Start(crc64PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                md5CtxData = new Md5Context();

                var md5PktData = new HashPacket
                {
                    Context = md5CtxData,
                    Data    = data
                };

                md5ThreadData.Start(md5PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                sha1CtxData = new Sha1Context();

                var sha1PktData = new HashPacket
                {
                    Context = sha1CtxData,
                    Data    = data
                };

                sha1ThreadData.Start(sha1PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                sha256CtxData = new Sha256Context();

                var sha256PktData = new HashPacket
                {
                    Context = sha256CtxData,
                    Data    = data
                };

                sha256ThreadData.Start(sha256PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                sha384CtxData = new Sha384Context();

                var sha384PktData = new HashPacket
                {
                    Context = sha384CtxData,
                    Data    = data
                };

                sha384ThreadData.Start(sha384PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                sha512CtxData = new Sha512Context();

                var sha512PktData = new HashPacket
                {
                    Context = sha512CtxData,
                    Data    = data
                };

                sha512ThreadData.Start(sha512PktData);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                ssctxData = new SpamSumContext();

                var spamsumPktData = new HashPacket
                {
                    Context = ssctxData,
                    Data    = data
                };

                spamsumThreadData.Start(spamsumPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                f16CtxData = new Fletcher16Context();

                var f16PktData = new HashPacket
                {
                    Context = f16CtxData,
                    Data    = data
                };

                f16ThreadData.Start(f16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                f32CtxData = new Fletcher32Context();

                var f32PktData = new HashPacket
                {
                    Context = f32CtxData,
                    Data    = data
                };

                f32ThreadData.Start(f32PktData);
            }

            while (adlerThreadData.IsAlive ||
                   crc16ThreadData.IsAlive ||
                   crc32ThreadData.IsAlive ||
                   crc64ThreadData.IsAlive ||
                   md5ThreadData.IsAlive ||
                   sha1ThreadData.IsAlive ||
                   sha256ThreadData.IsAlive ||
                   sha384ThreadData.IsAlive ||
                   sha512ThreadData.IsAlive ||
                   spamsumThreadData.IsAlive ||
                   f16ThreadData.IsAlive ||
                   f32ThreadData.IsAlive)
            {
            }

            List <ChecksumType> dataChecksums = new List <ChecksumType>();
            ChecksumType        chk;

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.adler32,
                    Value = adler32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc16,
                    Value = crc16CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc32,
                    Value = crc32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc64,
                    Value = crc64CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.md5,
                    Value = md5CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha1,
                    Value = sha1CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha256,
                    Value = sha256CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha384,
                    Value = sha384CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha512,
                    Value = sha512CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.spamsum,
                    Value = ssctxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.fletcher16,
                    Value = f16CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.fletcher32,
                    Value = f32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            return(dataChecksums);
        }
示例#6
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            if (stream.Length < 512)
            {
                return(false);
            }

            byte[] headerB = new byte[256];
            stream.Read(headerB, 0, 256);
            CpcDiskInfo header = Marshal.ByteArrayToStructureLittleEndian <CpcDiskInfo>(headerB);

            if (!_cpcdskId.SequenceEqual(header.magic.Take(_cpcdskId.Length)) &&
                !_edskId.SequenceEqual(header.magic) &&
                !_du54Id.SequenceEqual(header.magic))
            {
                return(false);
            }

            _extended = _edskId.SequenceEqual(header.magic);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Extended = {0}", _extended);

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.magic = \"{0}\"",
                                       StringHandlers.CToString(header.magic));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.magic2 = \"{0}\"",
                                       StringHandlers.CToString(header.magic2));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.creator = \"{0}\"",
                                       StringHandlers.CToString(header.creator));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracks = {0}", header.tracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.sides = {0}", header.sides);

            if (!_extended)
            {
                AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracksize = {0}", header.tracksize);
            }
            else
            {
                for (int i = 0; i < header.tracks; i++)
                {
                    for (int j = 0; j < header.sides; j++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "Track {0} Side {1} size = {2}", i, j,
                                                   header.tracksizeTable[(i * header.sides) + j] * 256);
                    }
                }
            }

            ulong currentSector = 0;

            _sectors      = new Dictionary <ulong, byte[]>();
            _addressMarks = new Dictionary <ulong, byte[]>();
            ulong readtracks        = 0;
            bool  allTracksSameSize = true;
            ulong sectorsPerTrack   = 0;

            // Seek to first track descriptor
            stream.Seek(256, SeekOrigin.Begin);

            for (int i = 0; i < header.tracks; i++)
            {
                for (int j = 0; j < header.sides; j++)
                {
                    // Track not stored in image
                    if (_extended && header.tracksizeTable[(i * header.sides) + j] == 0)
                    {
                        continue;
                    }

                    long trackPos = stream.Position;

                    byte[] trackB = new byte[256];
                    stream.Read(trackB, 0, 256);
                    CpcTrackInfo trackInfo = Marshal.ByteArrayToStructureLittleEndian <CpcTrackInfo>(trackB);

                    if (!_trackId.SequenceEqual(trackInfo.magic))
                    {
                        AaruConsole.ErrorWriteLine("Not the expected track info.");

                        return(false);
                    }

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].magic = \"{0}\"",
                                               StringHandlers.CToString(trackInfo.magic), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].bps = {0}",
                                               SizeCodeToBytes(trackInfo.bps), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].dataRate = {0}", trackInfo.dataRate,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].filler = 0x{0:X2}",
                                               trackInfo.filler, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].gap3 = 0x{0:X2}", trackInfo.gap3, i,
                                               j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].padding = {0}", trackInfo.padding,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].recordingMode = {0}",
                                               trackInfo.recordingMode, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sectors = {0}", trackInfo.sectors,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].side = {0}", trackInfo.side, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].track = {0}", trackInfo.track, i,
                                               j);

                    if (trackInfo.sectors != sectorsPerTrack)
                    {
                        if (sectorsPerTrack == 0)
                        {
                            sectorsPerTrack = trackInfo.sectors;
                        }
                        else
                        {
                            allTracksSameSize = false;
                        }
                    }

                    byte[][] thisTrackSectors      = new byte[trackInfo.sectors][];
                    byte[][] thisTrackAddressMarks = new byte[trackInfo.sectors][];

                    for (int k = 1; k <= trackInfo.sectors; k++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].id = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].id, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].len = {0}",
                                                   trackInfo.sectorsInfo[k - 1].len, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].side = {0}",
                                                   trackInfo.sectorsInfo[k - 1].side, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].size = {0}",
                                                   SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size), i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st1 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st1, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st2 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st2, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].track = {0}",
                                                   trackInfo.sectorsInfo[k - 1].track, i, j, k);

                        int sectLen = _extended ? trackInfo.sectorsInfo[k - 1].len
                                          : SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size);

                        byte[] sector = new byte[sectLen];
                        stream.Read(sector, 0, sectLen);

                        if (sectLen < SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, sector.Length);
                            sector = temp;
                        }
                        else if (sectLen > SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, temp.Length);
                            sector = temp;
                        }

                        thisTrackSectors[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = sector;

                        byte[] amForCrc = new byte[8];
                        amForCrc[0] = 0xA1;
                        amForCrc[1] = 0xA1;
                        amForCrc[2] = 0xA1;
                        amForCrc[3] = (byte)IBMIdType.AddressMark;
                        amForCrc[4] = trackInfo.sectorsInfo[k - 1].track;
                        amForCrc[5] = trackInfo.sectorsInfo[k - 1].side;
                        amForCrc[6] = trackInfo.sectorsInfo[k - 1].id;
                        amForCrc[7] = (byte)trackInfo.sectorsInfo[k - 1].size;

                        CRC16IBMContext.Data(amForCrc, 8, out byte[] amCrc);

                        byte[] addressMark = new byte[22];
                        Array.Copy(amForCrc, 0, addressMark, 12, 8);
                        Array.Copy(amCrc, 0, addressMark, 20, 2);

                        thisTrackAddressMarks[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = addressMark;
                    }

                    for (int s = 0; s < thisTrackSectors.Length; s++)
                    {
                        _sectors.Add(currentSector, thisTrackSectors[s]);
                        _addressMarks.Add(currentSector, thisTrackAddressMarks[s]);
                        currentSector++;

                        if (thisTrackSectors[s].Length > _imageInfo.SectorSize)
                        {
                            _imageInfo.SectorSize = (uint)thisTrackSectors[s].Length;
                        }
                    }

                    stream.Seek(trackPos, SeekOrigin.Begin);

                    if (_extended)
                    {
                        stream.Seek(header.tracksizeTable[(i * header.sides) + j] * 256, SeekOrigin.Current);
                        _imageInfo.ImageSize += (ulong)(header.tracksizeTable[(i * header.sides) + j] * 256) - 256;
                    }
                    else
                    {
                        stream.Seek(header.tracksize, SeekOrigin.Current);
                        _imageInfo.ImageSize += (ulong)header.tracksize - 256;
                    }

                    readtracks++;
                }
            }

            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} sectors", _sectors.Count);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} tracks", readtracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "All tracks are same size? {0}", allTracksSameSize);

            _imageInfo.Application          = StringHandlers.CToString(header.creator);
            _imageInfo.CreationTime         = imageFilter.GetCreationTime();
            _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
            _imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
            _imageInfo.Sectors      = (ulong)_sectors.Count;
            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            _imageInfo.MediaType    = MediaType.CompactFloppy;
            _imageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark);

            // Debug writing full disk as raw

            /*
             * FileStream foo = new FileStream(Path.GetFileNameWithoutExtension(imageFilter.GetFilename()) + ".bin", FileMode.Create);
             * for(ulong i = 0; i < (ulong)sectors.Count; i++)
             * {
             *  byte[] foob;
             *  sectors.TryGetValue(i, out foob);
             *  foo.Write(foob, 0, foob.Length);
             * }
             * foo.Close();
             */

            _imageInfo.Cylinders       = header.tracks;
            _imageInfo.Heads           = header.sides;
            _imageInfo.SectorsPerTrack = (uint)(_imageInfo.Sectors / (_imageInfo.Cylinders * _imageInfo.Heads));

            return(true);
        }
示例#7
0
        public void EmptyFile()
        {
            byte[] result = CRC16IBMContext.File(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"));

            result.Should().BeEquivalentTo(_expectedEmpty);
        }
示例#8
0
文件: CRC16IBM.cs 项目: paulyc/Aaru
        public void Crc16IbmEmptyFile()
        {
            byte[] result = CRC16IBMContext.File(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"));

            Assert.AreEqual(_expectedEmpty, result);
        }
示例#9
0
        public bool Open(IFilter imageFilter)
        {
            Stream stream = imageFilter.GetDataForkStream();

            stream.Seek(0, SeekOrigin.Begin);

            if (stream.Length < 512)
            {
                return(false);
            }

            byte[] headerB = new byte[256];
            stream.Read(headerB, 0, 256);

            int pos;

            for (pos = 0; pos < 254; pos++)
            {
                if (headerB[pos] == 0x0D &&
                    headerB[pos + 1] == 0x0A)
                {
                    break;
                }
            }

            if (pos >= 254)
            {
                return(false);
            }

            string magic = Encoding.ASCII.GetString(headerB, 0, pos);

            stream.Position = pos + 2;
            stream.Read(headerB, 0, 256);

            DiskInfo header = Marshal.ByteArrayToStructureLittleEndian <DiskInfo>(headerB);

            if (string.Compare(_cpcdskId, magic, StringComparison.InvariantCultureIgnoreCase) != 0 &&
                string.Compare(_edskId, magic, StringComparison.InvariantCultureIgnoreCase) != 0 &&
                string.Compare(_du54Id, magic, StringComparison.InvariantCultureIgnoreCase) != 0)
            {
                return(false);
            }

            _extended = string.Compare(_edskId, magic, StringComparison.InvariantCultureIgnoreCase) == 0;
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Extended = {0}", _extended);

            AaruConsole.DebugWriteLine("CPCDSK plugin", "magic = \"{0}\"", magic);

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.magic = \"{0}\"",
                                       StringHandlers.CToString(header.magic));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.creator = \"{0}\"",
                                       StringHandlers.CToString(header.creator));

            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracks = {0}", header.tracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "header.sides = {0}", header.sides);

            if (!_extended)
            {
                AaruConsole.DebugWriteLine("CPCDSK plugin", "header.tracksize = {0}", header.tracksize);
            }
            else
            {
                for (int i = 0; i < header.tracks; i++)
                {
                    for (int j = 0; j < header.sides; j++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "Track {0} Side {1} size = {2}", i, j,
                                                   header.tracksizeTable[(i * header.sides) + j] * 256);
                    }
                }
            }

            ulong currentSector = 0;

            _sectors      = new Dictionary <ulong, byte[]>();
            _addressMarks = new Dictionary <ulong, byte[]>();
            ulong readtracks        = 0;
            bool  allTracksSameSize = true;
            ulong sectorsPerTrack   = 0;

            // Seek to first track descriptor
            stream.Seek(256, SeekOrigin.Begin);

            for (int i = 0; i < header.tracks; i++)
            {
                for (int j = 0; j < header.sides; j++)
                {
                    // Track not stored in image
                    if (_extended && header.tracksizeTable[(i * header.sides) + j] == 0)
                    {
                        continue;
                    }

                    long trackPos = stream.Position;

                    byte[] trackB = new byte[256];
                    stream.Read(trackB, 0, 256);
                    TrackInfo trackInfo = Marshal.ByteArrayToStructureLittleEndian <TrackInfo>(trackB);

                    if (string.Compare(_trackId, Encoding.ASCII.GetString(trackInfo.magic),
                                       StringComparison.InvariantCultureIgnoreCase) != 0)
                    {
                        AaruConsole.ErrorWriteLine("Not the expected track info.");

                        return(false);
                    }

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].magic = \"{0}\"",
                                               StringHandlers.CToString(trackInfo.magic), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].bps = {0}",
                                               SizeCodeToBytes(trackInfo.bps), i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].dataRate = {0}", trackInfo.dataRate,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].filler = 0x{0:X2}",
                                               trackInfo.filler, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].gap3 = 0x{0:X2}", trackInfo.gap3, i,
                                               j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].padding = {0}", trackInfo.padding,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].recordingMode = {0}",
                                               trackInfo.recordingMode, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sectors = {0}", trackInfo.sectors,
                                               i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].side = {0}", trackInfo.side, i, j);

                    AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].track = {0}", trackInfo.track, i,
                                               j);

                    if (trackInfo.sectors != sectorsPerTrack)
                    {
                        if (sectorsPerTrack == 0)
                        {
                            sectorsPerTrack = trackInfo.sectors;
                        }
                        else
                        {
                            allTracksSameSize = false;
                        }
                    }

                    Dictionary <int, byte[]> thisTrackSectors      = new Dictionary <int, byte[]>();
                    Dictionary <int, byte[]> thisTrackAddressMarks = new Dictionary <int, byte[]>();

                    for (int k = 1; k <= trackInfo.sectors; k++)
                    {
                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].id = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].id, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].len = {0}",
                                                   trackInfo.sectorsInfo[k - 1].len, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].side = {0}",
                                                   trackInfo.sectorsInfo[k - 1].side, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].size = {0}",
                                                   SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size), i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st1 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st1, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].st2 = 0x{0:X2}",
                                                   trackInfo.sectorsInfo[k - 1].st2, i, j, k);

                        AaruConsole.DebugWriteLine("CPCDSK plugin", "trackInfo[{1}:{2}].sector[{3}].track = {0}",
                                                   trackInfo.sectorsInfo[k - 1].track, i, j, k);

                        int sectLen = _extended ? trackInfo.sectorsInfo[k - 1].len
                                          : SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size);

                        byte[] sector = new byte[sectLen];
                        stream.Read(sector, 0, sectLen);

                        if (sectLen < SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, sector.Length);
                            sector = temp;
                        }
                        else if (sectLen > SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size))
                        {
                            byte[] temp = new byte[SizeCodeToBytes(trackInfo.sectorsInfo[k - 1].size)];
                            Array.Copy(sector, 0, temp, 0, temp.Length);
                            sector = temp;
                        }

                        thisTrackSectors[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = sector;

                        byte[] amForCrc = new byte[8];
                        amForCrc[0] = 0xA1;
                        amForCrc[1] = 0xA1;
                        amForCrc[2] = 0xA1;
                        amForCrc[3] = (byte)IBMIdType.AddressMark;
                        amForCrc[4] = trackInfo.sectorsInfo[k - 1].track;
                        amForCrc[5] = trackInfo.sectorsInfo[k - 1].side;
                        amForCrc[6] = trackInfo.sectorsInfo[k - 1].id;
                        amForCrc[7] = (byte)trackInfo.sectorsInfo[k - 1].size;

                        CRC16IBMContext.Data(amForCrc, 8, out byte[] amCrc);

                        byte[] addressMark = new byte[22];
                        Array.Copy(amForCrc, 0, addressMark, 12, 8);
                        Array.Copy(amCrc, 0, addressMark, 20, 2);

                        thisTrackAddressMarks[(trackInfo.sectorsInfo[k - 1].id & 0x3F) - 1] = addressMark;
                    }

                    foreach (KeyValuePair <int, byte[]> s in thisTrackSectors.OrderBy(k => k.Key))
                    {
                        _sectors.Add(currentSector, s.Value);
                        _addressMarks.Add(currentSector, s.Value);
                        currentSector++;

                        if (s.Value.Length > _imageInfo.SectorSize)
                        {
                            _imageInfo.SectorSize = (uint)s.Value.Length;
                        }
                    }

                    stream.Seek(trackPos, SeekOrigin.Begin);

                    if (_extended)
                    {
                        stream.Seek(header.tracksizeTable[(i * header.sides) + j] * 256, SeekOrigin.Current);
                        _imageInfo.ImageSize += (ulong)(header.tracksizeTable[(i * header.sides) + j] * 256) - 256;
                    }
                    else
                    {
                        stream.Seek(header.tracksize, SeekOrigin.Current);
                        _imageInfo.ImageSize += (ulong)header.tracksize - 256;
                    }

                    readtracks++;
                }
            }

            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} sectors", _sectors.Count);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "Read {0} tracks", readtracks);
            AaruConsole.DebugWriteLine("CPCDSK plugin", "All tracks are same size? {0}", allTracksSameSize);

            _imageInfo.Application          = StringHandlers.CToString(header.creator);
            _imageInfo.CreationTime         = imageFilter.GetCreationTime();
            _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
            _imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
            _imageInfo.Sectors      = (ulong)_sectors.Count;
            _imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
            _imageInfo.MediaType    = MediaType.CompactFloppy;
            _imageInfo.ReadableSectorTags.Add(SectorTagType.FloppyAddressMark);

            _imageInfo.Cylinders       = header.tracks;
            _imageInfo.Heads           = header.sides;
            _imageInfo.SectorsPerTrack = (uint)(_imageInfo.Sectors / (_imageInfo.Cylinders * _imageInfo.Heads));

            return(true);
        }