示例#1
0
文件: Read.cs 项目: paulyc/Aaru
        public List <Track> GetSessionTracks(Session session)
        {
            if (_discImage.Sessions.Contains(session))
            {
                return(GetSessionTracks(session.SessionSequence));
            }

            throw new ImageNotSupportedException("Session does not exist in disc image");
        }
示例#2
0
文件: Read.cs 项目: 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);
            }
        }