public unsafe bool TestReadCommand() { if (readCommandFound) return true; //ReadCDCommand[] readmode = { ReadCDCommand.ReadCdBEh, ReadCDCommand.ReadCdD8h }; ReadCDCommand[] readmode = { ReadCDCommand.ReadCdBEh, ReadCDCommand.ReadCdD8h }; Device.C2ErrorMode[] c2mode = { Device.C2ErrorMode.Mode294, Device.C2ErrorMode.Mode296, Device.C2ErrorMode.None }; Device.MainChannelSelection[] mainmode = { Device.MainChannelSelection.UserData, Device.MainChannelSelection.F8h }; bool found = false; _autodetectResult = ""; _currentStart = 0; m_max_sectors = Math.Min(NSECTORS, m_device.MaximumTransferLength / CB_AUDIO - 1); int sector = 3; int pass = 0; for (int c = 0; c <= 2 && !found; c++) for (int r = 0; r <= 1 && !found; r++) for (int m = 0; m <= 1 && !found; m++) { _readCDCommand = readmode[r]; _c2ErrorMode = c2mode[c]; _mainChannelMode = mainmode[m]; if (_forceReadCommand != ReadCDCommand.Unknown && _readCDCommand != _forceReadCommand) continue; if (_readCDCommand == ReadCDCommand.ReadCdD8h && (_c2ErrorMode != Device.C2ErrorMode.None || _mainChannelMode != Device.MainChannelSelection.UserData)) continue; Array.Clear(_readBuffer, 0, _readBuffer.Length); // fill with something nasty instead? DateTime tm = DateTime.Now; if (ReadProgress != null) { progressArgs.Action = Resource1.StatusDetectingDriveFeatures; progressArgs.Pass = -1; progressArgs.Position = pass++; progressArgs.PassStart = 0; progressArgs.PassEnd = 2 * 3 * 2 - 1; progressArgs.ErrorsCount = 0; progressArgs.PassTime = tm; ReadProgress(this, progressArgs); } System.Diagnostics.Trace.WriteLine("Trying " + CurrentReadCommand); Device.CommandStatus st = FetchSectors(sector, m_max_sectors, false); TimeSpan delay = DateTime.Now - tm; _autodetectResult += string.Format("{0}: {1} ({2}ms)\n", CurrentReadCommand, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()), delay.TotalMilliseconds); found = st == Device.CommandStatus.Success; //sector += m_max_sectors; } //if (found) // for (int n = 1; n <= m_max_sectors; n++) // { // Device.CommandStatus st = FetchSectors(0, n, false, false); // if (st != Device.CommandStatus.Success) // { // _autodetectResult += string.Format("Maximum sectors: {0}, else {1}; max length {2}\n", n - 1, (st == Device.CommandStatus.DeviceFailed ? Device.LookupSenseError(m_device.GetSenseAsc(), m_device.GetSenseAscq()) : st.ToString()), m_device.MaximumTransferLength); // m_max_sectors = n - 1; // break; // } // } if (found) { TestGaps(); _autodetectResult += "Chosen " + CurrentReadCommand + "\n"; } else { _gapDetection = GapDetectionMethod.None; _readCDCommand = ReadCDCommand.Unknown; } _currentStart = -1; _currentEnd = -1; readCommandFound = found; return found; }
private unsafe void TestGaps() { _gapDetection = GapDetectionMethod.None; //st = m_device.Seek((uint)(sector + i * 33) + _toc[_toc.FirstAudio][0].Start); //if (st != Device.CommandStatus.Success) // break; //bool ready; //st = m_device.TestUnitReady(out ready); //if (st != Device.CommandStatus.Success) // break; //if (!ready) //{ // st = Device.CommandStatus.NotSupported; // break; //} // try ReadCD: Device.CommandStatus st; int sector = 3; if (_readCDCommand == ReadCDCommand.ReadCdBEh) { // PLEXTOR PX-W1210A always returns data, even if asked only for subchannel. // So we fill the buffer with magic data, give extra space for command so it won't hang the drive, // request subchannel data and check if magic data was overwritten. bool overwritten = false; for (int i = 0; i < 16; i++) { _subchannelBuffer[m_max_sectors * (588 * 4 + 16) - 16 + i] = (byte)(13 + i); } fixed (byte* data = _subchannelBuffer) { st = m_device.ReadCDAndSubChannel(Device.MainChannelSelection.None, Device.SubChannelMode.QOnly, Device.C2ErrorMode.None, 1, false, (uint)sector + _toc[_toc.FirstAudio][0].Start, (uint)m_max_sectors, (IntPtr)((void*)data), _timeout); } for (int i = 0; i < 16; i++) { if (_subchannelBuffer[m_max_sectors * (588 * 4 + 16) - 16 + i] != (byte)(13 + i)) overwritten = true; } if (overwritten) st = Device.CommandStatus.NotSupported; //else // st = m_device.ReadSubChannel(2, (uint)sector + _toc[_toc.FirstAudio][0].Start, (uint)m_max_sectors, ref _subchannelBuffer, _timeout); if (st == Device.CommandStatus.Success) { int[] goodsecs = new int[2]; for (int bcd = 1; bcd >= 0; bcd--) { for (int i = 0; i < m_max_sectors; i++) { int adr = _subchannelBuffer[i * 16 + 0] & 7; if (bcd == 0 && adr == 1) { _subchannelBuffer[i * 16 + 3] = toBCD(_subchannelBuffer[i * 16 + 3]); _subchannelBuffer[i * 16 + 4] = toBCD(_subchannelBuffer[i * 16 + 4]); _subchannelBuffer[i * 16 + 5] = toBCD(_subchannelBuffer[i * 16 + 5]); _subchannelBuffer[i * 16 + 7] = toBCD(_subchannelBuffer[i * 16 + 7]); _subchannelBuffer[i * 16 + 8] = toBCD(_subchannelBuffer[i * 16 + 8]); _subchannelBuffer[i * 16 + 9] = toBCD(_subchannelBuffer[i * 16 + 9]); } ushort crc = _crc.ComputeChecksum(_subchannelBuffer, i * 16, 10); crc ^= 0xffff; ushort scrc = (ushort)((_subchannelBuffer[i * 16 + 10] << 8) | _subchannelBuffer[i * 16 + 11]); if (scrc != 0 && scrc != crc) continue; if (adr != 1) continue; int sTrack = fromBCD(_subchannelBuffer[i * 16 + 1]); int sIndex = fromBCD(_subchannelBuffer[i * 16 + 2]); if (sTrack == 0 || sTrack == 110) continue; int mm = fromBCD(_subchannelBuffer[i * 16 + 7]); int ss = fromBCD(_subchannelBuffer[i * 16 + 8]); int ff = fromBCD(_subchannelBuffer[i * 16 + 9]); int sPos = ff + 75 * (ss + 60 * mm) - 150; if (sPos < sector + i - 8 || sPos > sector + i + 8) continue; goodsecs[bcd]++; } } if (goodsecs[0] > 0 || goodsecs[1] > 0) { _qChannelInBCD = goodsecs[1] >= goodsecs[0]; _gapDetection = GapDetectionMethod.ReadCD; } } } if (_gapDetection == GapDetectionMethod.None) { fixed (byte* data = _subchannelBuffer) { // seek to given sector if (_readCDCommand == ReadCDCommand.ReadCdBEh) st = m_device.ReadCDAndSubChannel(_mainChannelMode, Device.SubChannelMode.None, _c2ErrorMode, 1, false, (uint)sector + _toc[_toc.FirstAudio][0].Start, 1, (IntPtr)((void*)data), _timeout); else st = m_device.ReadCDDA(Device.SubChannelMode.None, (uint)sector + _toc[_toc.FirstAudio][0].Start, 1, (IntPtr)((void*)data), _timeout); } if (st == Device.CommandStatus.Success) { st = m_device.ReadSubChannel42(1, 0, ref _subchannelBuffer, 0, _timeout); if (st == Device.CommandStatus.Success) { if (_subchannelBuffer[0] == 0 && _subchannelBuffer[2] == 0 && _subchannelBuffer[3] == 12 && _subchannelBuffer[4] == 1) { int ctl = _subchannelBuffer[5] & 0xf; int adr = (_subchannelBuffer[5] >> 4) & 0xf; if (adr == 1) { _gapDetection = GapDetectionMethod.ReadSubchannel; } } } } } }