📄 aspilib.c
字号:
if ( cdHandles[idx].sm.ccsmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.ccsm[10] << 8) + (DWORD)cdHandles[idx].sm.ccsm[11];
}
break;
case CDP_BUFSIZE:
if ( cdHandles[idx].sm.ccsmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.ccsm[12] << 8) + (DWORD)cdHandles[idx].sm.ccsm[13];
}
break;
case CDP_CURRSPEED:
if ( cdHandles[idx].sm.ccsmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.ccsm[14] << 8) + (DWORD)cdHandles[idx].sm.ccsm[15];
}
break;
case CDP_SPM:
if ( cdHandles[idx].sm.cpmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.cpm[4] << 8) + (DWORD)cdHandles[idx].sm.cpm[5];
}
break;
case CDP_FPS:
if ( cdHandles[idx].sm.cpmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.cpm[6] << 8) + (DWORD)cdHandles[idx].sm.cpm[7];
}
break;
case CDP_INACTMULT:
if ( cdHandles[idx].sm.cpmAvail )
{
retVal = TRUE;
*pNum = (DWORD)(cdHandles[idx].sm.cpm[3] & 0x0F);
}
break;
case CDP_MSF:
retVal = cdHandles[idx].bMSF;
break;
case CDP_JITTER:
retVal = TRUE;
*pNum = (DWORD)(cdHandles[idx].numCheck);
break;
case CDP_OVERLAP:
retVal = TRUE;
*pNum = (DWORD)(cdHandles[idx].numOverlap);
break;
case CDP_READMODE:
retVal = TRUE;
*pNum = (DWORD)(cdHandles[idx].readMode);
break;
default:
break;
}
ReleaseMutex( cdMutexes[idx] );
return retVal;
}
/*
* Complement to queryCDParms -- used to set values in the various control
* pages on the CD drive.
*/
BOOL ModifyCDParms( HCDROM hCD, int which, DWORD val )
{
//SENSEMASK smask;
//BOOL smRead = FALSE;
BOOL retVal = FALSE;
int idx = (int)hCD - 1;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return FALSE;
}
if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
#if 0
if ( readCDParameters( hCD, TRUE ) != SS_COMP )
{
ReleaseMutex( cdMutexes[idx] );
return FALSE;
}
#endif
switch( which )
{
case CDP_CURRSPEED:
if ( setCDSpeed( hCD, val ) == SS_COMP )
retVal = TRUE;
break;
case CDP_MSF:
cdHandles[idx].bMSF = (BOOL)val;
retVal = TRUE;
break;
case CDP_JITTER:
cdHandles[idx].numCheck = (int)val;
retVal = TRUE;
break;
case CDP_OVERLAP:
cdHandles[idx].numOverlap = (int)val;
retVal = TRUE;
break;
case CDP_READMODE:
cdHandles[idx].readMode = (int)val;
retVal = TRUE;
break;
}
ReleaseMutex( cdMutexes[idx] );
return retVal;
}
/*
* Speed is specified in KB/sec: 1x == 176, 2x == 353, 4x == 706
*
* To set to the maximum allowed speed, specify 0xFFFF. Attempting to set
* a speed higher than the allowed maximum speed should not cause an error,
* but should set the speed at the highest allowed value.
*/
DWORD setCDSpeed( HCDROM hCD, DWORD speed )
{
DWORD dwStatus;
HANDLE heventSRB;
SRB_ExecSCSICmd s;
int idx = (int)hCD - 1;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaID = cdHandles[idx].ha;
s.SRB_Target = cdHandles[idx].tgt;
s.SRB_Lun = cdHandles[idx].lun;
s.SRB_Flags = SRB_DIR_OUT | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)heventSRB;
s.CDBByte[0] = 0xBB;
s.CDBByte[2] = (BYTE)(speed >> 8);
s.CDBByte[3] = (BYTE)speed;
ResetEvent( heventSRB );
dwStatus = pfnSendASPI32Command( (LPSRB)&s );
if ( dwStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, DEFWAITLEN );
}
CloseHandle( heventSRB );
if ( s.SRB_Status != SS_COMP )
{
alErrCode = ALERR_ASPI;
alAspiErr = s.SRB_Status;
CloseHandle( cdMutexes[idx] );
return SS_ERR;
}
return s.SRB_Status;
}
DWORD pauseResumeCD( HCDROM hCD, BOOL bPause )
{
DWORD dwStatus;
HANDLE heventSRB;
SRB_ExecSCSICmd s;
int idx = (int)hCD - 1;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaID = cdHandles[idx].ha;
s.SRB_Target = cdHandles[idx].tgt;
s.SRB_Lun = cdHandles[idx].lun;
s.SRB_Flags = SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)heventSRB;
s.CDBByte[0] = 0x4B;
s.CDBByte[8] = bPause?0:1;
ResetEvent( heventSRB );
dwStatus = pfnSendASPI32Command( (LPSRB)&s );
if ( dwStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, DEFWAITLEN );
}
CloseHandle( heventSRB );
if ( s.SRB_Status != SS_COMP )
{
alErrCode = ALERR_ASPI;
alAspiErr = s.SRB_Status;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
ReleaseMutex( cdMutexes[idx] );
return s.SRB_Status;
}
DWORD startStopUnit( HCDROM hCD, BOOL bLoEj, BOOL bStart )
{
DWORD dwStatus;
HANDLE heventSRB;
SRB_ExecSCSICmd s;
int idx = (int)hCD - 1;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaID = cdHandles[idx].ha;
s.SRB_Target = cdHandles[idx].tgt;
s.SRB_Lun = cdHandles[idx].lun;
s.SRB_Flags = SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 6;
s.SRB_PostProc = (LPVOID)heventSRB;
s.CDBByte[0] = 0x1B;
s.CDBByte[4] |= bLoEj?0x02:0x00;
s.CDBByte[4] |= bStart?0x01:0x00;
ResetEvent( heventSRB );
dwStatus = pfnSendASPI32Command( (LPSRB)&s );
if ( dwStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, DEFWAITLEN );
}
CloseHandle( heventSRB );
if ( s.SRB_Status != SS_COMP )
{
alErrCode = ALERR_ASPI;
alAspiErr = s.SRB_Status;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
ReleaseMutex( cdMutexes[idx] );
return s.SRB_Status;
}
/****************************************************************
* GetAspiLibError
*
* Used after functions return SS_ERR to get more specific error
* information. If it returns AL_ERRASPI, call getAspiLibAspiError
* to get the actual status code returned by the calls to the ASPI
* manager. After reading, the error code is cleared.
*
****************************************************************/
int GetAspiLibError( void )
{
int retVal;
retVal = alErrCode;
alErrCode = ALERR_NOERROR;
return retVal;
}
/****************************************************************
* GetAspiLibAspiError
*
* Returns the last error completion code from the ASPI manager.
* After reading, the error code is cleared.
*
****************************************************************/
BYTE GetAspiLibAspiError( void )
{
BYTE retVal;
retVal = alAspiErr;
alAspiErr = SS_COMP;
return retVal;
}
/****************************************************************
* GetCDId
*
* Generates an identifier string for the CD drive identified by
* hCD
*
****************************************************************/
DWORD GetCDId( HCDROM hCD, char *buf, int maxBuf )
{
int idx = (int)hCD - 1;
CDREC cd;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
if ( !buf )
{
alErrCode = ALERR_BUFPTR;
return SS_ERR;
}
if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
memset( &cd, 0, sizeof(cd) );
GetDriveInfo( cdHandles[idx].ha, cdHandles[idx].tgt, cdHandles[idx].lun,
&cd );
if ( strlen( cd.id ) > maxBuf-1 )
{
alErrCode = ALERR_BUFTOOSMALL;
strncpy( buf, cd.id, maxBuf );
buf[maxBuf-1] = '\0';
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
else
strcpy( buf, cd.id );
ReleaseMutex( cdMutexes[idx] );
return SS_COMP;
}
/*
* Returns TRUE if the overlap buffer is located in the track buffer. The
* track buffer startOffset is adjusted to reflect where in the buffer the
* aligned data begins. numFrames and len are also adjusted to reflect the
* number of complete frames are contained in the buffer.
*/
int jitterAdjust( LPTRACKBUF tbuf, LPTRACKBUF tover, int checkFrames )
{
int i;
int max;
int bFound = 0;
BYTE *p;
int checkLen = checkFrames * 2352;
max = tbuf->len - checkLen;
if ( tover->len == 0 )
return 1;
p = &tover->buf[tover->startOffset];
bFound = 0;
for( i = 0; i < max; i++ )
{
if ( compBuf( p, &(tbuf->buf[i]), checkLen ) )
{
tbuf->startOffset = i + checkLen;
tbuf->len -= (i + checkLen);
tbuf->startFrame = tover->startFrame + checkFrames;
i = max + 1;
bFound = -1;
}
}
/* adjust frame count and crop length */
tbuf->numFrames = tbuf->len / 2352;
tbuf->len = 2352 * tbuf->numFrames;
// return (tbuf->startOffset == 0);
return bFound;
}
/*
* Reads CD-DA audio, implementing jitter correction. tOver is used to align
* the current read, if possible. After a successful read, numOverlap frames
* are copied to tOver.
*/
DWORD ReadCDAudioLBAEx( HCDROM hCD, LPTRACKBUF t, LPTRACKBUF tOver )
{
DWORD retVal;
int idx = (int)hCD - 1;
int j, o;
unsigned char *pOverAddr;
BOOL bJitterCorr;
if ( (idx<0) || (idx>=MAXCDHAND) )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
retVal = WaitForSingleObject( cdMutexes[idx], TIMEOUT );
if ( retVal != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
if ( !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
j = cdHandles[idx].numCheck;
o = cdHandles[idx].numOverlap;
// check that the overlap buffer is large enough -- if not, disable
// jitter correction. We may want to eventually throw an error
bJitterCorr = ((tOver->maxLen / 2352) >= o);
#ifdef _DEBUG
dbprintf( "akrip32: ReadCDAudioLBAEx( t->startFrame == %08X, tOver->startFrame == %08X, j == %d )", t->startFrame, tOver->startFrame, j );
dbprintf( " : t: %08X %d %d", t->startFrame, t->numFrames, t->len );
dbprintf( " : tOver: %08X %d %d", tOver->startFrame, tOver->numFrames, tOver->len );
#endif
// adjust the starting address of the read if necessary
if ( bJitterCorr && tOver->startFrame && tOver->numFrames && tOver->len )
{
// is this tOver from the last sequential read?
if ( tOver->startFrame == (t->startFrame - j) )
{
#ifdef _DEBUG
dbprintf( "Rolling back the read..." );
#endif
t->startFrame -= o;
}
else
{
#ifdef _DEBUG
dbprintf( "Zeroing out the overlap!" );
#endif
tOver->len = tOver->startFrame = tOver->numFrames = 0;
}
}
retVal = cdHandles[idx].pfnRead( hCD, t );
if ( (retVal == SS_COMP) && bJitterCorr )
{
#ifdef _DEBUG
dbprintf( "akrip32: ReadCDAudioLBAEx: read itself OK" );
#endif
j = cdHandles[idx].numCheck;
if ( !jitterAdjust( t, tOver, j ) )
{
#ifdef _DEBUG
dbprintf( "akrip32: ... jitterAdjust failed!" );
#endif
alErrCode = ALERR_JITTER;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
#ifdef _DEBUG
dbprintf( "akrip32: ... after successful jitter adjust" );
#endif
pOverAddr = &(t->buf[2352*(t->numFrames-j)+t->startOffset]);
memcpy( tOver->buf, pOverAddr, 2352*j );
tOver->startFrame = t->startFrame + t->numFrames - j;
tOver->numFrames = j;
tOver->len = 2352 * j;
tOver->startOffset = 0;
}
#ifdef _DEBUG
else
dbprintf( "akrip32: ReadCDAudioLBAEx: read failed" );
#endif
ReleaseMutex( cdMutexes[idx] );
#ifdef _DEBUG
dbprintf( "akrip32: readCDAudioLBAEx: returning %04X", retVal );
#endif
return retVal;
}
/********************************************************************
* compBuf
*
* Compares two buffers up to n bytes, returning 1 if they contain the
* same data, or zero if they are different.
*
********************************************************************/
int compBuf( BYTE *b1, BYTE *b2, int n )
{
#if 0
int i;
for( i = 0; i < n; i++ )
if ( b1[i] != b2[i] )
{
return 0;
}
return 1;
#else
return !memcmp( b1, b2, n );
#endif
}
DWORD GetAKRipDllVersion( void )
{
DWORD retVal;
retVal = (DWORD)( (((WORD)MAJVER)<<16) | (WORD)MINVER );
return retVal;
}
void dbprintf( char *fmt, ... )
{
char buf[512];
va_list arg;
va_start( arg, fmt );
vsprintf( buf, fmt, arg );
OutputDebugString( buf );
va_end( arg );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -