Esempio n. 1
0
File: Read.cs Progetto: paulyc/Aaru
        public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
        {
            if (track == 0)
            {
                if (sectorAddress + length > _densitySeparationSectors)
                {
                    throw new ArgumentOutOfRangeException(nameof(length),
                                                          "Requested more sectors than present in track, won't cross tracks");
                }

                return(new byte[length * 2352]);
            }

            var aaruTrack = new GdiTrack
            {
                Sequence = 0
            };

            foreach (GdiTrack gdiTrack in _discImage.Tracks.Where(gdiTrack => gdiTrack.Sequence == track))
            {
                aaruTrack = gdiTrack;

                break;
            }

            if (aaruTrack.Sequence == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image");
            }

            if (sectorAddress + length > aaruTrack.Sectors)
            {
                throw new ArgumentOutOfRangeException(nameof(length),
                                                      "Requested more sectors than present in track, won't cross tracks");
            }

            uint sectorOffset;
            uint sectorSize;
            uint sectorSkip;

            switch (aaruTrack.TrackType)
            {
            case TrackType.Audio:
            {
                sectorOffset = 0;
                sectorSize   = 2352;
                sectorSkip   = 0;

                break;
            }

            case TrackType.CdMode1:
            {
                if (aaruTrack.Bps == 2352)
                {
                    sectorOffset = 0;
                    sectorSize   = 2352;
                    sectorSkip   = 0;
                }
                else
                {
                    sectorOffset = 0;
                    sectorSize   = 2048;
                    sectorSkip   = 0;
                }

                break;
            }

            default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
            }

            byte[] buffer = new byte[sectorSize * length];

            ulong remainingSectors = length;

            if (aaruTrack.Pregap > 0 &&
                sectorAddress < aaruTrack.Pregap)
            {
                ulong remainingPregap = aaruTrack.Pregap - sectorAddress;

                remainingSectors -= length > remainingPregap ? remainingPregap : length;
            }

            if (remainingSectors == 0)
            {
                return(buffer);
            }

            _imageStream = aaruTrack.TrackFilter.GetDataForkStream();
            var br = new BinaryReader(_imageStream);

            long pos = aaruTrack.Offset + (long)((sectorAddress * (sectorOffset + sectorSize + sectorSkip)) -
                                                 (aaruTrack.Pregap * aaruTrack.Bps));

            if (pos < 0)
            {
                pos = 0;
            }

            br.BaseStream.Seek(pos, SeekOrigin.Begin);

            if (sectorOffset == 0 &&
                sectorSkip == 0 &&
                remainingSectors == length)
            {
                buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
            }
            else if (sectorOffset == 0 &&
                     sectorSkip == 0)
            {
                byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
                Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
            }
            else
            {
                int bufferPos = (int)((length - remainingSectors) * sectorSize);

                for (ulong i = 0; i < remainingSectors; i++)
                {
                    br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
                    byte[] sector = br.ReadBytes((int)sectorSize);
                    br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
                    Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
                    bufferPos += (int)sectorSize;
                }
            }

            switch (aaruTrack.TrackType)
            {
            case TrackType.CdMode1 when aaruTrack.Bps == 2048:
            {
                byte[] fullSector = new byte[2352];
                byte[] fullBuffer = new byte[2352 * length];

                for (uint i = 0; i < length; i++)
                {
                    Array.Copy(buffer, i * 2048, fullSector, 16, 2048);
                    _sectorBuilder.ReconstructPrefix(ref fullSector, TrackType.CdMode1, (long)(sectorAddress + i));
                    _sectorBuilder.ReconstructEcc(ref fullSector, TrackType.CdMode1);
                    Array.Copy(fullSector, 0, fullBuffer, i * 2352, 2352);
                }

                buffer = fullBuffer;

                break;
            }
            }

            return(buffer);
        }
Esempio n. 2
0
File: Read.cs Progetto: paulyc/Aaru
        public bool Open(IFilter imageFilter)
        {
            if (imageFilter == null)
            {
                return(false);
            }

            try
            {
                imageFilter.GetDataForkStream().Seek(0, SeekOrigin.Begin);
                _gdiStream = new StreamReader(imageFilter.GetDataForkStream());
                int  lineNumber  = 0;
                bool highDensity = false;

                // Initialize all RegExs
                var regexTrack = new Regex(REGEX_TRACK);

                // Initialize all RegEx matches

                // Initialize disc
                _discImage = new GdiDisc
                {
                    Sessions = new List <Session>(),
                    Tracks   = new List <GdiTrack>()
                };

                ulong currentStart = 0;
                _offsetMap = new Dictionary <uint, ulong>();
                _densitySeparationSectors = 0;

                while (_gdiStream.Peek() >= 0)
                {
                    lineNumber++;
                    string line = _gdiStream.ReadLine();

                    if (lineNumber == 1)
                    {
                        if (!int.TryParse(line, out _))
                        {
                            throw new ImageNotSupportedException("Not a correct Dreamcast GDI image");
                        }
                    }
                    else
                    {
                        Match trackMatch = regexTrack.Match(line ?? throw new InvalidOperationException());

                        if (!trackMatch.Success)
                        {
                            throw new ImageNotSupportedException($"Unknown line \"{line}\" at line {lineNumber}");
                        }

                        AaruConsole.DebugWriteLine("GDI plugin",
                                                   "Found track {0} starts at {1} flags {2} type {3} file {4} offset {5} at line {6}",
                                                   trackMatch.Groups["track"].Value, trackMatch.Groups["start"].Value,
                                                   trackMatch.Groups["flags"].Value, trackMatch.Groups["type"].Value,
                                                   trackMatch.Groups["filename"].Value,
                                                   trackMatch.Groups["offset"].Value, lineNumber);

                        var filtersList = new FiltersList();

                        var currentTrack = new GdiTrack
                        {
                            Bps         = ushort.Parse(trackMatch.Groups["type"].Value),
                            Flags       = byte.Parse(trackMatch.Groups["flags"].Value),
                            Offset      = long.Parse(trackMatch.Groups["offset"].Value),
                            Sequence    = uint.Parse(trackMatch.Groups["track"].Value),
                            StartSector = ulong.Parse(trackMatch.Groups["start"].Value),
                            TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(),
                                                                             trackMatch.Groups["filename"].Value.
                                                                             Replace("\\\"", "\"").Trim('"')))
                        };

                        currentTrack.TrackFile = currentTrack.TrackFilter.GetFilename();

                        if (currentTrack.StartSector - currentStart > 0)
                        {
                            if (currentTrack.StartSector == 45000)
                            {
                                highDensity = true;
                                _offsetMap.Add(0, currentStart);
                                _densitySeparationSectors = currentTrack.StartSector - currentStart;
                                currentStart = currentTrack.StartSector;
                            }
                            else
                            {
                                currentTrack.Pregap       = currentTrack.StartSector - currentStart;
                                currentTrack.StartSector -= currentTrack.StartSector - currentStart;
                            }
                        }

                        if ((currentTrack.TrackFilter.GetDataForkLength() - currentTrack.Offset) % currentTrack.Bps != 0)
                        {
                            throw new ImageNotSupportedException("Track size not a multiple of sector size");
                        }

                        currentTrack.Sectors =
                            (ulong)((currentTrack.TrackFilter.GetDataForkLength() - currentTrack.Offset) /
                                    currentTrack.Bps);

                        currentTrack.Sectors    += currentTrack.Pregap;
                        currentStart            += currentTrack.Sectors;
                        currentTrack.HighDensity = highDensity;

                        currentTrack.TrackType =
                            (currentTrack.Flags & 0x4) == 0x4 ? TrackType.CdMode1 : TrackType.Audio;

                        _discImage.Tracks.Add(currentTrack);
                    }
                }

                Session[] sessions = new Session[2];

                for (int s = 0; s < sessions.Length; s++)
                {
                    if (s == 0)
                    {
                        sessions[s].SessionSequence = 1;

                        foreach (GdiTrack trk in _discImage.Tracks.Where(trk => !trk.HighDensity))
                        {
                            if (sessions[s].StartTrack == 0)
                            {
                                sessions[s].StartTrack = trk.Sequence;
                            }
                            else if (sessions[s].StartTrack > trk.Sequence)
                            {
                                sessions[s].StartTrack = trk.Sequence;
                            }

                            if (sessions[s].EndTrack < trk.Sequence)
                            {
                                sessions[s].EndTrack = trk.Sequence;
                            }

                            if (sessions[s].StartSector > trk.StartSector)
                            {
                                sessions[s].StartSector = trk.StartSector;
                            }

                            if (sessions[s].EndSector < (trk.Sectors + trk.StartSector) - 1)
                            {
                                sessions[s].EndSector = (trk.Sectors + trk.StartSector) - 1;
                            }
                        }
                    }
                    else
                    {
                        sessions[s].SessionSequence = 2;

                        foreach (GdiTrack trk in _discImage.Tracks.Where(trk => trk.HighDensity))
                        {
                            if (sessions[s].StartTrack == 0)
                            {
                                sessions[s].StartTrack = trk.Sequence;
                            }
                            else if (sessions[s].StartTrack > trk.Sequence)
                            {
                                sessions[s].StartTrack = trk.Sequence;
                            }

                            if (sessions[s].EndTrack < trk.Sequence)
                            {
                                sessions[s].EndTrack = trk.Sequence;
                            }

                            if (sessions[s].StartSector > trk.StartSector)
                            {
                                sessions[s].StartSector = trk.StartSector;
                            }

                            if (sessions[s].EndSector < (trk.Sectors + trk.StartSector) - 1)
                            {
                                sessions[s].EndSector = (trk.Sectors + trk.StartSector) - 1;
                            }
                        }
                    }
                }

                _discImage.Sessions.Add(sessions[0]);
                _discImage.Sessions.Add(sessions[1]);

                _discImage.Disktype = MediaType.GDROM;

                // DEBUG information
                AaruConsole.DebugWriteLine("GDI plugin", "Disc image parsing results");

                AaruConsole.DebugWriteLine("GDI plugin", "Session information:");
                AaruConsole.DebugWriteLine("GDI plugin", "\tDisc contains {0} sessions", _discImage.Sessions.Count);

                for (int i = 0; i < _discImage.Sessions.Count; i++)
                {
                    AaruConsole.DebugWriteLine("GDI plugin", "\tSession {0} information:", i + 1);

                    AaruConsole.DebugWriteLine("GDI plugin", "\t\tStarting track: {0}",
                                               _discImage.Sessions[i].StartTrack);

                    AaruConsole.DebugWriteLine("GDI plugin", "\t\tStarting sector: {0}",
                                               _discImage.Sessions[i].StartSector);

                    AaruConsole.DebugWriteLine("GDI plugin", "\t\tEnding track: {0}", _discImage.Sessions[i].EndTrack);

                    AaruConsole.DebugWriteLine("GDI plugin", "\t\tEnding sector: {0}",
                                               _discImage.Sessions[i].EndSector);
                }

                AaruConsole.DebugWriteLine("GDI plugin", "Track information:");
                AaruConsole.DebugWriteLine("GDI plugin", "\tDisc contains {0} tracks", _discImage.Tracks.Count);

                for (int i = 0; i < _discImage.Tracks.Count; i++)
                {
                    AaruConsole.DebugWriteLine("GDI plugin", "\tTrack {0} information:", _discImage.Tracks[i].Sequence);
                    AaruConsole.DebugWriteLine("GDI plugin", "\t\t{0} bytes per sector", _discImage.Tracks[i].Bps);
                    AaruConsole.DebugWriteLine("GDI plugin", "\t\tPregap: {0} sectors", _discImage.Tracks[i].Pregap);

                    if ((_discImage.Tracks[i].Flags & 0x8) == 0x8)
                    {
                        AaruConsole.DebugWriteLine("GDI plugin", "\t\tTrack is flagged as quadraphonic");
                    }

                    if ((_discImage.Tracks[i].Flags & 0x4) == 0x4)
                    {
                        AaruConsole.DebugWriteLine("GDI plugin", "\t\tTrack is data");
                    }

                    if ((_discImage.Tracks[i].Flags & 0x2) == 0x2)
                    {
                        AaruConsole.DebugWriteLine("GDI plugin", "\t\tTrack allows digital copy");
                    }

                    if ((_discImage.Tracks[i].Flags & 0x1) == 0x1)
                    {
                        AaruConsole.DebugWriteLine("GDI plugin", "\t\tTrack has pre-emphasis applied");
                    }

                    AaruConsole.DebugWriteLine("GDI plugin",
                                               "\t\tTrack resides in file {0}, type defined as {1}, starting at byte {2}",
                                               _discImage.Tracks[i].TrackFilter, _discImage.Tracks[i].TrackType,
                                               _discImage.Tracks[i].Offset);
                }

                AaruConsole.DebugWriteLine("GDI plugin", "Building offset map");

                Partitions = new List <Partition>();
                ulong byteOffset = 0;

                for (int i = 0; i < _discImage.Tracks.Count; i++)
                {
                    if (_discImage.Tracks[i].Sequence == 1 &&
                        i != 0)
                    {
                        throw new ImageNotSupportedException("Unordered tracks");
                    }

                    // Index 01
                    var partition = new Partition
                    {
                        Description = $"Track {_discImage.Tracks[i].Sequence}.",
                        Name        = null,
                        Start       = _discImage.Tracks[i].StartSector,
                        Size        = _discImage.Tracks[i].Sectors * _discImage.Tracks[i].Bps,
                        Length      = _discImage.Tracks[i].Sectors,
                        Sequence    = _discImage.Tracks[i].Sequence,
                        Offset      = byteOffset,
                        Type        = _discImage.Tracks[i].TrackType.ToString()
                    };

                    byteOffset += partition.Size;
                    _offsetMap.Add(_discImage.Tracks[i].Sequence, partition.Start);
                    Partitions.Add(partition);
                }

                foreach (GdiTrack track in _discImage.Tracks)
                {
                    _imageInfo.ImageSize += track.Bps * track.Sectors;
                }

                foreach (GdiTrack track in _discImage.Tracks)
                {
                    _imageInfo.Sectors += track.Sectors;
                }

                _imageInfo.Sectors += _densitySeparationSectors;

                _imageInfo.SectorSize = 2352; // All others

                foreach (GdiTrack unused in _discImage.Tracks.Where(track => (track.Flags & 0x4) == 0x4 &&
                                                                    track.Bps == 2352))
                {
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ);
                    _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc);
                }

                _imageInfo.CreationTime         = imageFilter.GetCreationTime();
                _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();

                _imageInfo.MediaType = _discImage.Disktype;

                _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);

                _imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;

                AaruConsole.VerboseWriteLine("GDI image describes a disc of type {0}", _imageInfo.MediaType);

                _sectorBuilder = new SectorBuilder();

                return(true);
            }
            catch (Exception ex)
            {
                AaruConsole.ErrorWriteLine("Exception trying to identify image file {0}", imageFilter.GetBasePath());
                AaruConsole.ErrorWriteLine("Exception: {0}", ex.Message);
                AaruConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace);

                return(false);
            }
        }
Esempio n. 3
0
File: Read.cs Progetto: paulyc/Aaru
        public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
        {
            if (tag == SectorTagType.CdTrackFlags)
            {
                track = (uint)sectorAddress;
            }

            if (track == 0)
            {
                if (sectorAddress + length > _densitySeparationSectors)
                {
                    throw new ArgumentOutOfRangeException(nameof(length),
                                                          "Requested more sectors than present in track, won't cross tracks");
                }

                if (tag == SectorTagType.CdTrackFlags)
                {
                    return new byte[]
                           {
                               0x00
                           }
                }
                ;

                throw new ArgumentException("Unsupported tag requested for this track", nameof(tag));
            }

            var aaruTrack = new GdiTrack
            {
                Sequence = 0
            };

            foreach (GdiTrack gdiTrack in _discImage.Tracks.Where(gdiTrack => gdiTrack.Sequence == track))
            {
                aaruTrack = gdiTrack;

                break;
            }

            if (aaruTrack.Sequence == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image");
            }

            if (length > aaruTrack.Sectors)
            {
                throw new ArgumentOutOfRangeException(nameof(length),
                                                      "Requested more sectors than present in track, won't cross tracks");
            }

            uint sectorOffset;
            uint sectorSize;
            uint sectorSkip;

            switch (tag)
            {
            case SectorTagType.CdSectorEcc:
            case SectorTagType.CdSectorEccP:
            case SectorTagType.CdSectorEccQ:
            case SectorTagType.CdSectorEdc:
            case SectorTagType.CdSectorHeader:
            case SectorTagType.CdSectorSync: break;

            case SectorTagType.CdTrackFlags:
            {
                byte[] flags = new byte[1];

                flags[0] += aaruTrack.Flags;

                return(flags);
            }

            default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
            }

            switch (aaruTrack.TrackType)
            {
            case TrackType.Audio: throw new ArgumentException("There are no tags on audio tracks", nameof(tag));

            case TrackType.CdMode1:
            {
                if (aaruTrack.Bps != 2352)
                {
                    throw new FeatureNotPresentImageException("Image does not include tags for mode 1 sectors");
                }

                switch (tag)
                {
                case SectorTagType.CdSectorSync:
                {
                    sectorOffset = 0;
                    sectorSize   = 12;
                    sectorSkip   = 2340;

                    break;
                }

                case SectorTagType.CdSectorHeader:
                {
                    sectorOffset = 12;
                    sectorSize   = 4;
                    sectorSkip   = 2336;

                    break;
                }

                case SectorTagType.CdSectorSubchannel:
                case SectorTagType.CdSectorSubHeader:
                    throw new ArgumentException("Unsupported tag requested for this track", nameof(tag));

                case SectorTagType.CdSectorEcc:
                {
                    sectorOffset = 2076;
                    sectorSize   = 276;
                    sectorSkip   = 0;

                    break;
                }

                case SectorTagType.CdSectorEccP:
                {
                    sectorOffset = 2076;
                    sectorSize   = 172;
                    sectorSkip   = 104;

                    break;
                }

                case SectorTagType.CdSectorEccQ:
                {
                    sectorOffset = 2248;
                    sectorSize   = 104;
                    sectorSkip   = 0;

                    break;
                }

                case SectorTagType.CdSectorEdc:
                {
                    sectorOffset = 2064;
                    sectorSize   = 4;
                    sectorSkip   = 284;

                    break;
                }

                default: throw new ArgumentException("Unsupported tag requested", nameof(tag));
                }

                break;
            }

            default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
            }

            byte[] buffer = new byte[sectorSize * length];

            ulong remainingSectors = length;

            if (aaruTrack.Pregap > 0 &&
                sectorAddress < aaruTrack.Pregap)
            {
                ulong remainingPregap = aaruTrack.Pregap - sectorAddress;

                remainingSectors -= length > remainingPregap ? remainingPregap : length;
            }

            if (remainingSectors == 0)
            {
                return(buffer);
            }

            _imageStream = aaruTrack.TrackFilter.GetDataForkStream();
            var br = new BinaryReader(_imageStream);

            long pos = aaruTrack.Offset + (long)((sectorAddress * (sectorOffset + sectorSize + sectorSkip)) -
                                                 (aaruTrack.Pregap * aaruTrack.Bps));

            if (pos < 0)
            {
                pos = 0;
            }

            br.BaseStream.Seek(pos, SeekOrigin.Begin);

            if (sectorOffset == 0 &&
                sectorSkip == 0 &&
                remainingSectors == length)
            {
                buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
            }
            else if (sectorOffset == 0 &&
                     sectorSkip == 0)
            {
                byte[] tmp = br.ReadBytes((int)(sectorSize * remainingSectors));
                Array.Copy(tmp, 0, buffer, (int)((length - remainingSectors) * sectorSize), tmp.Length);
            }
            else
            {
                int bufferPos = (int)((length - remainingSectors) * sectorSize);

                for (ulong i = 0; i < remainingSectors; i++)
                {
                    br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
                    byte[] sector = br.ReadBytes((int)sectorSize);
                    br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
                    Array.Copy(sector, 0, buffer, bufferPos, sectorSize);
                    bufferPos += (int)sectorSize;
                }
            }

            return(buffer);
        }
Esempio n. 4
0
        public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
        {
            if (track == 0)
            {
                if (sectorAddress + length > densitySeparationSectors)
                {
                    throw new ArgumentOutOfRangeException(nameof(length),
                                                          "Requested more sectors than present in track, won't cross tracks");
                }

                return(new byte[length * 2352]);
            }

            GdiTrack dicTrack = new GdiTrack {
                Sequence = 0
            };

            foreach (GdiTrack gdiTrack in discimage.Tracks.Where(gdiTrack => gdiTrack.Sequence == track))
            {
                dicTrack = gdiTrack;
                break;
            }

            if (dicTrack.Sequence == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image");
            }

            if (sectorAddress + length > dicTrack.Sectors)
            {
                throw new ArgumentOutOfRangeException(nameof(length),
                                                      "Requested more sectors than present in track, won't cross tracks");
            }

            uint sectorOffset;
            uint sectorSize;
            uint sectorSkip;

            switch (dicTrack.Tracktype)
            {
            case TrackType.Audio:
            {
                sectorOffset = 0;
                sectorSize   = 2352;
                sectorSkip   = 0;
                break;
            }

            case TrackType.CdMode1:
            {
                if (dicTrack.Bps == 2352)
                {
                    sectorOffset = 0;
                    sectorSize   = 2352;
                    sectorSkip   = 0;
                }
                else
                {
                    sectorOffset = 0;
                    sectorSize   = 2048;
                    sectorSkip   = 0;
                }

                break;
            }

            default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
            }

            byte[] buffer = new byte[sectorSize * length];

            ulong remainingSectors = length;

            if (dicTrack.Pregap > 0 && sectorAddress < dicTrack.Pregap)
            {
                ulong  remainingPregap = dicTrack.Pregap - sectorAddress;
                byte[] zero;
                if (length > remainingPregap)
                {
                    zero              = new byte[remainingPregap * sectorSize];
                    remainingSectors -= remainingPregap;
                }
                else
                {
                    zero              = new byte[length * sectorSize];
                    remainingSectors -= length;
                }

                Array.Copy(zero, 0, buffer, 0, zero.Length);
            }

            if (remainingSectors == 0)
            {
                return(buffer);
            }

            imageStream = dicTrack.Trackfilter.GetDataForkStream();
            BinaryReader br = new BinaryReader(imageStream);

            br.BaseStream
            .Seek(dicTrack.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip) + dicTrack.Pregap * dicTrack.Bps),
                  SeekOrigin.Begin);
            if (sectorOffset == 0 && sectorSkip == 0)
            {
                buffer = br.ReadBytes((int)(sectorSize * remainingSectors));
            }
            else
            {
                for (ulong i = 0; i < remainingSectors; i++)
                {
                    br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
                    byte[] sector = br.ReadBytes((int)sectorSize);
                    br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
                    Array.Copy(sector, 0, buffer, (int)(i * sectorSize), sectorSize);
                }
            }

            return(buffer);
        }