示例#1
0
        public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag)
        {
            if (!IsWriting)
            {
                ErrorMessage = "Tried to write on a non-writable image";

                return(false);
            }

            Track track =
                Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
                                      sectorAddress <= trk.TrackEndSector);

            if (track is null)
            {
                ErrorMessage = $"Can't found track containing {sectorAddress}";

                return(false);
            }

            switch (tag)
            {
            case SectorTagType.CdTrackFlags:
            case SectorTagType.CdTrackIsrc: return(WriteSectorTag(data, sectorAddress, tag));

            case SectorTagType.CdSectorSubchannel:
            {
                if (track.TrackSubchannelType == 0)
                {
                    ErrorMessage =
                        $"Trying to write subchannel to track {track.TrackSequence}, that does not have subchannel";

                    return(false);
                }

                if (data.Length % 96 != 0)
                {
                    ErrorMessage = "Incorrect data size for subchannel";

                    return(false);
                }

                if (_subStream == null)
                {
                    try
                    {
                        _subStream = new FileStream(_writingBaseName + ".sub", FileMode.OpenOrCreate,
                                                    FileAccess.ReadWrite, FileShare.None);
                    }
                    catch (IOException e)
                    {
                        ErrorMessage = $"Could not create subchannel file, exception {e.Message}";

                        return(false);
                    }
                }

                _subStream.
                Seek((long)(track.TrackSubchannelOffset + ((sectorAddress - track.TrackStartSector) * 96)),
                     SeekOrigin.Begin);

                _subStream.Write(Subchannel.Deinterleave(data), 0, data.Length);

                return(true);
            }

            default:
                ErrorMessage = $"Unsupported tag type {tag}";

                return(false);
            }
        }
示例#2
0
文件: Subchannel.cs 项目: radtek/Aaru
        // Return true if indexes have changed
        bool WriteSubchannelToImage(MmcSubchannel supportedSubchannel, MmcSubchannel desiredSubchannel, byte[] sub,
                                    ulong sectorAddress, uint length, SubchannelLog subLog,
                                    Dictionary <byte, string> isrcs, byte currentTrack, ref string mcn, Track[] tracks)
        {
            if (supportedSubchannel == MmcSubchannel.Q16)
            {
                sub = Subchannel.ConvertQToRaw(sub);
            }

            if (desiredSubchannel != MmcSubchannel.None)
            {
                _outputPlugin.WriteSectorsTag(sub, sectorAddress, length, SectorTagType.CdSectorSubchannel);
            }

            subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, length);

            byte[] deSub = Subchannel.Deinterleave(sub);

            // Check subchannel
            for (int subPos = 0; subPos < deSub.Length; subPos += 96)
            {
                byte[] q = new byte[12];
                Array.Copy(deSub, subPos + 12, q, 0, 12);

                CRC16CCITTContext.Data(q, 10, out byte[] crc);
                bool crcOk = crc[0] == q[10] && crc[1] == q[11];

                // ISRC
                if ((q[0] & 0x3) == 3)
                {
                    string isrc = Subchannel.DecodeIsrc(q);

                    if (isrc == null ||
                        isrc == "000000000000")
                    {
                        continue;
                    }

                    if (!crcOk)
                    {
                        continue;
                    }

                    if (!isrcs.ContainsKey(currentTrack))
                    {
                        _dumpLog?.WriteLine($"Found new ISRC {isrc} for track {currentTrack}.");
                        UpdateStatus?.Invoke($"Found new ISRC {isrc} for track {currentTrack}.");
                    }
                    else if (isrcs[currentTrack] != isrc)
                    {
                        _dumpLog?.
                        WriteLine($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");

                        UpdateStatus?.
                        Invoke($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");
                    }

                    isrcs[currentTrack] = isrc;
                }
                else if ((q[0] & 0x3) == 2)
                {
                    string newMcn = Subchannel.DecodeMcn(q);

                    if (newMcn == null ||
                        newMcn == "0000000000000")
                    {
                        continue;
                    }

                    if (!crcOk)
                    {
                        continue;
                    }

                    if (mcn is null)
                    {
                        _dumpLog?.WriteLine($"Found new MCN {newMcn}.");
                        UpdateStatus?.Invoke($"Found new MCN {newMcn}.");
                    }
                    else if (mcn != newMcn)
                    {
                        _dumpLog?.WriteLine($"MCN changed from {mcn} to {newMcn}.");
                        UpdateStatus?.Invoke($"MCN changed from {mcn} to {newMcn}.");
                    }

                    mcn = newMcn;
                }
                else if ((q[0] & 0x3) == 1)
                {
                    // TODO: Indexes

                    // Pregap
                    if (q[2] != 0)
                    {
                        continue;
                    }

                    if (!crcOk)
                    {
                        continue;
                    }

                    byte trackNo = (byte)(((q[1] / 16) * 10) + (q[1] & 0x0F));

                    for (int i = 0; i < tracks.Length; i++)
                    {
                        if (tracks[i].TrackSequence != trackNo ||
                            trackNo == 1)
                        {
                            continue;
                        }

                        byte pmin   = (byte)(((q[3] / 16) * 10) + (q[3] & 0x0F));
                        byte psec   = (byte)(((q[4] / 16) * 10) + (q[4] & 0x0F));
                        byte pframe = (byte)(((q[5] / 16) * 10) + (q[5] & 0x0F));
                        int  qPos   = (pmin * 60 * 75) + (psec * 75) + pframe;

                        if (tracks[i].TrackPregap >= (ulong)(qPos + 1))
                        {
                            continue;
                        }

                        tracks[i].TrackPregap       = (ulong)(qPos + 1);
                        tracks[i].TrackStartSector -= tracks[i].TrackPregap;

                        if (i > 0)
                        {
                            tracks[i - 1].TrackEndSector = tracks[i].TrackStartSector - 1;
                        }

                        _dumpLog?.WriteLine($"Pregap for track {trackNo} set to {tracks[i].TrackPregap} sectors.");
                        UpdateStatus?.Invoke($"Pregap for track {trackNo} set to {tracks[i].TrackPregap} sectors.");

                        return(true);
                    }
                }
            }

            return(false);
        }