| vbAccelerator - Contents of code file: CDRip_CDExtract.cppThis file is part of the download CDRip DLL Source, which is described in the article CD Ripping in VB Part 1. /*
** Copyright (C) 1999 Albert L. Faber
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "StdAfx.h"
#include <Stdio.h>
#include <Stdlib.h>
#include "vector"
#include "CDRip.h"
using namespace std ;
#include "CDExtract.h"
#include "AspiDebug.h"
#include <math.h>
static BOOL g_bParanoiaJitterErrors = FALSE;
SENSEKEY g_SenseKey;
// CONSTRUCTOR
CCDExtract::CCDExtract()
:CAspiCD()
{
m_nPeakValue = 0;
m_pbtReadBuffer = NULL;
m_pbtOverlapBuffer = NULL;
m_pbtReadBufferCompare = NULL;
m_nBeginSector = 0;
m_nEndSector = 0;
m_nJitterPos = 50;
m_nJitterErrors = 0;
m_lSector = 0;
m_dwBytesToDo = 0;
m_pParanoia = NULL;
m_pParanoiaDrive = NULL;
m_nCurrentSpeed = 0;
m_nLastSpeedAdjust = -1;
m_pbAbort = NULL;
}
// DESRUCTOR
CCDExtract::~CCDExtract()
{
// de-allocate memory buffers
delete [] m_pbtReadBuffer; m_pbtReadBuffer=NULL;
// de-allocate Multiple read memory buffers
delete [] m_pbtReadBufferCompare;m_pbtReadBufferCompare=NULL;
// de-allocate memory buffers
delete [] m_pbtOverlapBuffer; m_pbtOverlapBuffer=NULL;
delete m_pParanoiaDrive;
if ( m_pParanoia ) paranoia_free( m_pParanoia );
m_pParanoia = NULL;
m_pParanoiaDrive = NULL;
}
BOOL CCDExtract::SetupTrackExtract(int nBeginSector,int nEndSector)
{
DebugPrintf("Entering CCDExtract::SetupTrackExtract");
// Reset current sector
m_lSector=0;
m_nCurrentSpeed = GetSpeed();
m_nLastSpeedAdjust = -1;
// Allocate memory for a read buffers
m_pbtReadBuffer=new BYTE[GetNumReadSectors() * CB_CDDASECTOR];
// Allocate memory for multi read buffers
m_pbtReadBufferCompare=new BYTE[GetNumReadSectors() * CB_CDDASECTOR];
// Allocate memory for the two read buffers
if (GetNumCompareSectors()>0)
m_pbtOverlapBuffer=new BYTE[GetNumCompareSectors() * CB_CDDASECTOR];
else
m_pbtOverlapBuffer=NULL;
// Rip at leat 10 sectors
if (nBeginSector+10>nEndSector)
nEndSector=nBeginSector+10;
// Set starting point
m_nBeginSector=max((long)nBeginSector+(long)GetOffsetStart(),0);
// Set end point
m_nEndSector=(long)nEndSector+(long)GetOffsetEnd();
// Call to enable CDDA (needed for certain drives)
EnableCdda(TRUE);
// Don't allow a CD change while recording
PreventMediaRemoval (TRUE);
SetScsiTimeOut(10);
int nTimeout=GetScsiTimeOut();
DebugPrintf("Timeout is set to %d",nTimeout);
// Clear number of jitter errors
m_nJitterErrors=0;
// Clear peak value
m_nPeakValue=0;
// Set First Read = TRUE
m_bFirstRead=TRUE;
m_dwBytesToDo=CB_CDDASECTOR*(m_nEndSector-m_nBeginSector);
DebugPrintf("Leaving CCDExtract::SetupTrackExtract");
return TRUE;
}
BOOL CCDExtract::SetupTrackExtractParanoia( int nBeginSector,int nEndSector )
{
DebugPrintf("Entering CCDExtract::SetupTrackExtractParanoia");
if (m_pParanoia == NULL) {
// first time -> allocate paranoia structure
m_pParanoiaDrive = new cdrom_drive;
m_pParanoiaDrive->cdr = this;
m_pParanoiaDrive->nsectors = GetNumReadSectors();
m_pParanoia = paranoia_init( m_pParanoiaDrive );
}
int nParanoiaMode = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP;
switch ( GetParanoiaMode() )
{
case 0:
nParanoiaMode = PARANOIA_MODE_OVERLAP;
break;
case 1:
nParanoiaMode &= ~PARANOIA_MODE_VERIFY;
break;
case 2:
nParanoiaMode &= ~( PARANOIA_MODE_SCRATCH | PARANOIA_MODE_REPAIR );
break;
case 3:
// use default setting
break;
default:
ASSERT( FALSE );
break;
}
paranoia_modeset( m_pParanoia, nParanoiaMode );
// Reset current sector
m_lSector=0;
// Allocate memory for a read buffers
m_pbtReadBuffer=new BYTE[ GetNumReadSectors() * CB_CDDASECTOR ];
// Allocate memory for multi read buffers
m_pbtReadBufferCompare=new BYTE[ GetNumReadSectors() * CB_CDDASECTOR ];
// Allocate memory for the two read buffers
if ( GetNumCompareSectors()>0 )
{
m_pbtOverlapBuffer=new BYTE[ GetNumCompareSectors() * CB_CDDASECTOR ];
}
else
{
m_pbtOverlapBuffer=NULL;
}
// Rip at leat 10 sectors
if ( nBeginSector + 10 > nEndSector )
{
nEndSector = nBeginSector+10;
}
// Set starting point
m_nBeginSector = max((long)nBeginSector+(long)GetOffsetStart(),0);
// Set end point
m_nEndSector = (long)nEndSector + (long)GetOffsetEnd();
m_lSector = m_nBeginSector;
paranoia_set_range( m_pParanoia, m_nBeginSector, m_nEndSector - 1 );
// Call to enable CDDA (needed for certain drives
EnableCdda(TRUE);
// Don't allow a CD change while recording
PreventMediaRemoval (TRUE);
SetScsiTimeOut(10);
int nTimeout=GetScsiTimeOut();
DebugPrintf("Timeout is set to %d",nTimeout);
// Clear number of jitter errors
m_nJitterErrors=0;
// Clear peak value
m_nPeakValue=0;
// Set First Read = TRUE
m_bFirstRead=TRUE;
m_dwBytesToDo = CB_CDDASECTOR * ( m_nEndSector - m_nBeginSector );
DebugPrintf("Leaving CCDExtract::SetupTrackExtractParanoia");
return TRUE;
}
BOOL CCDExtract::EndTrackExtract()
{
DebugPrintf("Entering CCDExtract::EndTrackExtract");
// de-allocate memory buffers
delete [] m_pbtReadBuffer; m_pbtReadBuffer=NULL;
delete [] m_pbtReadBufferCompare; m_pbtReadBufferCompare = NULL;
// de-allocate memory buffers
delete [] m_pbtOverlapBuffer; m_pbtOverlapBuffer=NULL;
delete m_pParanoiaDrive;
if ( m_pParanoia )
{
paranoia_free( m_pParanoia );
m_pParanoia = NULL;
}
m_pParanoia = NULL;
m_pParanoiaDrive = NULL;
// Disable CDDA (needed for certain drives)
EnableCdda( FALSE );
// Allow a CD removal again
PreventMediaRemoval( FALSE );
m_pbAbort = NULL;
DebugPrintf("Leaving CCDExtract::EndTrackExtract");
return FALSE;
}
// now, figure out how many blocks to keep (jitter control)
// |-------- previous --------|
// |----------- buffer --------|
// we need to match the end of previous and start of buffer
// so we do a match, and compute how many bytes of overlap
// to skip (bytes_to_skip)
DWORD CCDExtract::CorrectJitter(BYTE* pbtOverlapPtr,BYTE* pbtReadPtr,DWORD
dwBytesRead,BOOL& bJitterError)
{
DebugPrintf("Entering CCDExtract::CorrectJitter");
BOOL bFound = FALSE;
int nOffset=0;
int nCompareBytes=(int)GetNumCompareSectors()*(int)CB_CDDASECTOR;
int
nMaxByteCompare=min(2*(int)GetNumOverlapSectors()*(int)CB_CDDASECTOR,dwBytes
Read)-(int)nCompareBytes;
int nStartCompare=nMaxByteCompare/2;
int nSkipBytes=nStartCompare;
BYTE* pbtLCmp=pbtReadPtr+nStartCompare;
BYTE* pbtHCmp=pbtReadPtr+nStartCompare;
bJitterError=FALSE;
if (pbtOverlapPtr==NULL)
{
DebugPrintf("Leaving CCDExtract::CorrectJitter, pbtOverlapPtr=NULL");
return 0;
}
if (pbtReadPtr==NULL)
{
DebugPrintf("Leaving CCDExtract::CorrectJitter, pbtReadPtr==NULL");
return 0;
}
if (dwBytesRead==0)
{
DebugPrintf("Leaving CCDExtract::CorrectJitter, dwBytesRead==0");
return 0;
}
if (nMaxByteCompare<=0)
{
DebugPrintf("Leaving CCDExtract::CorrectJitter, nMaxByteCompare<=0");
return 0;
}
for (nOffset = 0; nOffset<nStartCompare; nOffset+=4,pbtLCmp-=4,pbtHCmp+=4)
{
if (memcmp( pbtOverlapPtr, pbtLCmp,nCompareBytes) == 0)
{
nSkipBytes= nStartCompare-nOffset+nCompareBytes;
bFound = TRUE;
break;
}
if (memcmp( pbtOverlapPtr, pbtHCmp,nCompareBytes) == 0)
{
nSkipBytes= nStartCompare+nOffset+nCompareBytes;
bFound = TRUE;
break;
}
}
if (!bFound && dwBytesRead>nCompareBytes)
{
bJitterError=TRUE;
m_nJitterErrors++;
DebugPrintf("Detected a jitter error in CCDExtract");
}
if (nMaxByteCompare)
m_nJitterPos=(nSkipBytes-nCompareBytes)*100/nMaxByteCompare;
else
m_nJitterPos=50;
ASSERT( nSkipBytes<dwBytesRead);
ASSERT( nSkipBytes>=0);
if (nSkipBytes<0)
nSkipBytes=0;
if (nSkipBytes>=dwBytesRead)
nSkipBytes=dwBytesRead-1;
DebugPrintf("Entering CCDExtract::CorrectJitter with nSkipBytes=%5d
JitterPos=%5d",nSkipBytes,m_nJitterPos);
return nSkipBytes;
/*
if (!bFound)
{
// Try using a more advanced jitter correction!!
// Find max correlation
nOffset=CB_CDDASECTOR*((nORD)GetNumOverlapSectors()-(nORD)GetNumCompareSec
tors());
pbtLCmp=m_pbtReadBuffer+nOffset;
pbtHCmp=m_pbtReadBuffer+nOffset;
nORD nMaxCorrPos=0;
double dMinDiff=1.0E99;
// Look backwards
for (i = 0; i < nOffset; i+=4)
{
double dDiff=0.0;
int j;
for (j=0;j<CB_CDDASECTOR * GetNumCompareSectors();j++)
{
dDiff+=fabs(m_pbtOverlapBuffer[j]-pbtLCmp[j]);
}
if (dDiff<dMinDiff)
{
dMinDiff=dDiff;
nBytesToSkip=nOffset-i + CB_CDDASECTOR * GetNumCompareSectors();
}
dDiff=0.0;
for (j=0;j<CB_CDDASECTOR * GetNumCompareSectors();j++)
{
dDiff+=fabs(m_pbtOverlapBuffer[j]-pbtHCmp[j]);
}
if (dDiff<dMinDiff)
{
dMinDiff=dDiff;
nBytesToSkip=nOffset+i + CB_CDDASECTOR * GetNumCompareSectors();
}
pbtLCmp-=4;
pbtHCmp+=4;
}
bJitterError=TRUE;
nBytesToSkip=nOffset;
//AfxMessageBox(" Jitter correction failed, increase the Read Overlap
value in the configure dialog box");
}
*/
/*
#ifdef DEBUG_VERBOSE
CString strTmp;
strTmp.Format("Jitter Control: matched overlap %d , nominal value %d bytes
\n ",nBytesToSkip-CB_CDDASECTOR * GetNumCompareSectors(), CB_CDDASECTOR *
(GetNumOverlapSectors()-GetNumCompareSectors()));
DebugPrintf(strTmp);
#endif
return nBytesToSkip ;
*/
}
static char *callback_strings[15]={
"wrote",
"finished",
"read",
"verify",
"jitter",
"correction",
"scratch",
"scratch repair",
"skip",
"drift",
"backoff",
"overlap",
"dropped",
"duped",
"transport error"
};
void CCDExtract::paranoiaCallback( long inpos , int function )
{
DebugPrintf("Callback sector %08d code %d string %s \n", inpos/2352 ,
function, (function>=-2&&function<=13?callback_strings[function+2]:"") );
switch ( function )
{
case PARANOIA_CB_SKIP:
g_bParanoiaJitterErrors = TRUE;
break;
}
}
CDEX_ERR CCDExtract::RipChunkParanoia( BYTE* pbtStream, LONG* pNumBytes, BOOL&
bAbort )
{
*pNumBytes = 0;
m_pbAbort = &bAbort;
g_bParanoiaJitterErrors = FALSE;
if ( 0 == m_dwBytesToDo )
{
SetPercentCompleted( 100 );
return CDEX_RIPPING_DONE;
}
if (m_bFirstRead)
{
// Get starting sector which has to be copied
m_lSector = m_nBeginSector;
SetCDSpeed();
// Spin up the CD Rom if necessary
DWORD dwStart=::GetTickCount();
while ( (::GetTickCount()-dwStart)<(DWORD)GetSpinUpTime()*1000)
{
// Read cd rom sector to Spin up the CD-ROM
DebugPrintf("Reading Paranoia sector %d", m_lSector );
ReadCdRomSector( m_pbtReadBuffer, m_lSector,1, FALSE );
}
m_bFirstRead = FALSE;
}
if ( m_pParanoia )
{
int nBlock = 0;
DebugPrintf("Current, %8d Start %8d End %8d dwByteToDo %8d \n",
m_lSector,
m_nBeginSector,
m_nEndSector,
m_dwBytesToDo );
for ( nBlock = 0; nBlock < GetNumReadSectors(); nBlock++ )
{
// function return only one sector
short* buf = paranoia_read( m_pParanoia,
&CCDExtract::paranoiaCallback, &bAbort );
if ( NULL == buf )
return CDEX_ERROR;
*pNumBytes+= 2352;
memcpy( pbtStream + nBlock * 2352, buf, 2352 );
m_dwBytesToDo -= min( m_dwBytesToDo, 2352 );
if ( 0 == m_dwBytesToDo )
{
SetPercentCompleted( 100 );
return CDEX_OK;
}
}
if ( g_bParanoiaJitterErrors )
{
m_nJitterErrors++;
}
m_lSector+= GetNumReadSectors();
int nSectorsToDo = (m_nEndSector - m_lSector);
SetPercentCompleted((int)( 100.0- (DOUBLE)nSectorsToDo * 100.0/ (
m_nEndSector - m_nBeginSector ) ) );
// Calculate Peak Value
short* psValue=(short*)(pbtStream);
// Determine peak value
for ( DWORD dwSample=0;dwSample< *pNumBytes/2; dwSample++ )
{
m_nPeakValue=max( abs( psValue[dwSample] ),m_nPeakValue );
}
if ( g_bParanoiaJitterErrors )
return CDEX_JITTER_ERROR;
return CDEX_OK;
}
return CDEX_ERROR;
}
CDEX_ERR CCDExtract::RipChunk( BYTE* pbtStream, LONG* pNumBytes, BOOL& bAbort )
{
static LONG lSectorEnd;
static LONG nSectorsToDo;
static DWORD dwSkipBytes=0;
static DWORD dwSkipBytesCompare=0;
static DWORD dwBytes=0;
BOOL bJitterCorr=FALSE;
LONG lOverlapSamples=GetNumOverlapSectors();
DebugPrintf( "Entering CCDExtract::RipChunk" );
if ( GetJitterCorrection() && ( GetNumOverlapSectors()>0 ) )
{
bJitterCorr=TRUE;
}
else
{
lOverlapSamples=0;
}
if ( NULL == pNumBytes )
{
ASSERT( FALSE );
return CDEX_ERROR;
}
else
{
*pNumBytes=0;
}
if ( NULL == pbtStream || NULL == m_pbtReadBuffer )
{
ASSERT( FALSE );
return CDEX_ERROR;
}
if ( m_bFirstRead )
{
// Get starting sector which has to be copied
m_lSector = m_nBeginSector;
// Get last sector which has to be copied
lSectorEnd = m_nEndSector;
// calculate # of sectors to read
nSectorsToDo = (m_nEndSector - m_lSector);
// Set the CD ripping speed
SetCDSpeed();
// Spin up the CD Rom if necessary
DWORD dwStart=::GetTickCount();
while ( (::GetTickCount()-dwStart)<(DWORD)GetSpinUpTime()*1000)
{
// Read cd rom sector to Spin up the CD-ROM
ReadCdRomSector( m_pbtReadBuffer, m_lSector, 1, FALSE );
}
}
// Loop through all the tracks, maybe something for a user thread in the
near future
// if (nSectorsToDo <=GetNumOverlapSectors())
if ( 0 == m_dwBytesToDo )
{
SetPercentCompleted( 100 );
return CDEX_RIPPING_DONE;
}
// Set recording percentage complete
if ( (m_nEndSector - m_nBeginSector) != 0 )
{
SetPercentCompleted( (int)( 100.0 -(DOUBLE)nSectorsToDo * 100.0 / (
m_nEndSector - m_nBeginSector ) ) );
}
else
{
SetPercentCompleted( 0 );
}
BYTE* pbtWritePtr=NULL;
DWORD dwBufferOffset = GetNumCompareSectors() * CB_CDDASECTOR;
BOOL bJitterError=FALSE;
LONG nSectorsToRead= min( nSectorsToDo, GetNumReadSectors() );
// Handle last sectors correctly
// FIXME, CAN ALL DRIVERS HANDLE READING BEYOND THE LEAD LOCATION ?
if ( nSectorsToRead <= GetNumOverlapSectors() )
{
// In this situation, we have to read the overlap area + the amount of
sectors
// that still have to be done.
nSectorsToRead= min( GetNumOverlapSectors() +nSectorsToDo,
GetNumReadSectors() );
}
DebugPrintf( "nSectorsToDo=%d nSectorsToRead=%d
m_lSector=%d",nSectorsToDo,nSectorsToRead,m_lSector );
// We are reading only m_nReadSector*CB_CDDASECTOR bytes
DWORD dwBytesRead= nSectorsToRead * CB_CDDASECTOR;
// Should we do the multiple reads
BOOL bJitterErrorCompare = FALSE;
BOOL bReadMatch = FALSE;
BOOL doMultiReads = FALSE;
#if 0
BOOL doMultiReads = TRUE;
if ((GetMultiReadEnable() == FALSE) ||
(GetMultiRead() <= 0) ||
((GetMultiReadFirstOnly() == TRUE) && (!m_bFirstRead)))
{
doMultiReads = FALSE;
}
#endif
// Read Multiple times and continue when match
while ( FALSE == bReadMatch )
{
// Default is to pass, will mark fail if found
bReadMatch = TRUE;
// Normal Read
ReadChunk(nSectorsToRead, lOverlapSamples, bJitterCorr, dwBytesRead,
bJitterError, dwSkipBytes, m_pbtReadBuffer);
// Read the compare blocks
for (int rereads = 0; (bReadMatch) && (doMultiReads) && (rereads <
GetMultiRead()) ; rereads++)
{
// Read the block
ReadChunk(nSectorsToRead, lOverlapSamples, bJitterCorr, dwBytesRead,
bJitterErrorCompare, dwSkipBytesCompare, m_pbtReadBufferCompare);
// Compare
for (int compareIndex = 0; (compareIndex +
max(dwSkipBytes,dwSkipBytesCompare)) < dwBytesRead; compareIndex++)
{
if (
m_pbtReadBuffer[dwSkipBytes + compareIndex] !=
m_pbtReadBufferCompare[dwSkipBytesCompare + compareIndex]
)
{
bReadMatch = FALSE;
continue;
}
}
}
}
// If we did the multi read we need to copy the last block so the parameters
that were
// set in the read, like m_nJitterPos and m_nJitterErrors, will apply to the
current
// data
if ( doMultiReads == TRUE )
{
memcpy(m_pbtReadBuffer,m_pbtReadBufferCompare,dwBytesRead);
}
// Calculate Peak Value
short* psValue=(short*)(m_pbtReadBuffer);
// Determine peak value
for ( DWORD dwSample=0; dwSample<dwBytesRead/2; dwSample++ )
{
m_nPeakValue=max( abs( psValue[ dwSample ] ),m_nPeakValue );
}
// Set beginning of
pbtWritePtr = m_pbtReadBuffer + dwSkipBytes;
// Copy the compare region upfront
if ( GetNumCompareSectors() > 0 && m_pbtOverlapBuffer )
{
int nBytesToCopy=GetNumCompareSectors() * CB_CDDASECTOR;
int nCopyOffset=dwBytesRead-nBytesToCopy;
if (nCopyOffset<0)
{
nCopyOffset=0;
nBytesToCopy=dwBytesRead;
}
// Some debug logging, error prone code in CDex 1.20 beta 7!
DebugPrintf("Copy overlap buffer, nCopyOffset=%d
nBytesToCopy=%d",nCopyOffset,nBytesToCopy);
memcpy(m_pbtOverlapBuffer,m_pbtReadBuffer+nCopyOffset,nBytesToCopy);
}
// Set number of output bytes
*pNumBytes=min( dwBytesRead - dwSkipBytes, m_dwBytesToDo );
// Clip in case of last sector
// Debug information
DebugPrintf("copy data dwBytesRead=%d pNumBytes=%d
dwSkipBytes=%d",dwBytesRead,*pNumBytes,dwSkipBytes);
// Copy byte stream
memcpy( pbtStream, pbtWritePtr, *pNumBytes );
// Increase the sector offset
m_lSector+=(nSectorsToRead-lOverlapSamples );
// Lower the number of sectors still to do
nSectorsToDo-= ( nSectorsToRead - lOverlapSamples );
// Lower number of bytes todo
m_dwBytesToDo-= *pNumBytes;
DebugPrintf("Leaving CCDExtract::RipChunk");
if ( bJitterError )
return CDEX_JITTER_ERROR;
// And close CD device
return CDEX_OK;
}
void CCDExtract::GetLastJitterErrorPosition(DWORD& dwStartSector,DWORD&
dwEndSector)
{
dwStartSector=m_lSector-(GetNumReadSectors()-GetNumOverlapSectors());
dwEndSector=m_lSector;
}
void CCDExtract::ReadChunk(const long nSectorsToRead, const long
lOverlapSamples, const BOOL bJitterCorr, const DWORD dwBytesRead, BOOL
&bJitterError, DWORD &dwSkipBytes, PBYTE readBuffer)
{
// Read Chunk from CD-ROM
if (((ReadCdRomSector(readBuffer,m_lSector,nSectorsToRead, FALSE ) )==FALSE)
&&
(GetAspiRetries()>0)
)
{
// If there was an error slow down the CDROM and try again
::Sleep(1000);
SetCDSpeed( 1 );
DebugPrintf("Switch to lower Read Speed\n");
// Read previous tracks first to sync up again
for (int nRetro=0;nRetro<GetAspiRetries();nRetro++)
{
// Reduce READ speed to 1
SetCDSpeed( 1 );
if ( FALSE == ReadCdRomSector(readBuffer,150+nRetro*10,10, FALSE ) )
{
DebugPrintf("ReadCdRomSector not OK in retry: %d\n",nRetro);
::Sleep(GetAspiTimeOut());
}
}
// Try it again
ReadCdRomSector( readBuffer, m_lSector, nSectorsToRead, FALSE );
}
if ( !m_bFirstRead && bJitterCorr)
{
// Perform Jitter Correction
dwSkipBytes = CorrectJitter( m_pbtOverlapBuffer, readBuffer, dwBytesRead,
bJitterError );
}
else
{
dwSkipBytes=0;
m_bFirstRead=FALSE;
}
return;
}
// Interface for Monty's paranoia library:
// return the number of sectors?
long cdda_read(cdrom_drive *d, void *buffer, long beginsector, long sectors)
{
int nRetries = 0;
CCDExtract *cdr = (CCDExtract*)d->cdr;
// when 100 sectors have be read without a problem, revert to default speed
if ( ( ( beginsector - cdr->GetLastSectorSpeedAdjusted() ) > 500 ) &&
(-1 != cdr->GetLastSectorSpeedAdjusted() ) )
{
if ( cdr->GetCurrentSpeed() != cdr->GetSpeed() )
{
cdr->SetCDSpeed( );
cdr->GetLastSectorSpeedAdjusted( -1 );
}
}
if ( ( FALSE == cdr->ReadCdRomSector( (BYTE*)buffer, beginsector, sectors,
FALSE ) )
&& ( nRetries< 10 ) )
{
// read error, reduce spead if possible
int nSpeed = cdr->GetCurrentSpeed();
if ( nSpeed > 1)
{
::Sleep(1000);
cdr->GetLastSectorSpeedAdjusted( beginsector );
cdr->SetCDSpeed( 1 );
}
// do a dummy read at the begin sector to flush cache buffer
cdr->ReadCdRomSector( (BYTE*)buffer, cdr->GetBeginSector(), sectors,
FALSE );
// nRetries++;
sectors = -1;
}
/* return -999 incase the abort button has been pressed */
if ( cdr->GetAbort() )
{
sectors = -999;
}
return sectors;
}
| |||
|
|
||||