pcsx2/plugins/CDVDpeops/generic.c

387 lines
11 KiB
C

/***************************************************************************
generic.c - description
-------------------
begin : Sun Nov 16 2003
copyright : (C) 2003 by Pete Bernert
email : BlackDove@addcom.de
***************************************************************************/
/***************************************************************************
* *
* 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. See also the license.txt file for *
* additional informations. *
* *
***************************************************************************/
//*************************************************************************//
// History of changes:
//
// 2004/12/25 - Pete
// - repaired time2addr/addr2time
//
// 2003/11/16 - Pete
// - generic cleanup for the Peops release
//
//*************************************************************************//
/////////////////////////////////////////////////////////
#include "stdafx.h"
#define _IN_GENERIC
#include "externals.h"
/////////////////////////////////////////////////////////
int iCD_AD=-1; // drive address
int iCD_TA=-1;
int iCD_LU=-1;
int iRType=0; // read mode
int iUseSpeedLimit=0; // speed limit use
int iSpeedLimit=2; // speed 2x
int iNoWait=0; // wait
int iMaxRetry=5; // retry on error
int iShowReadErr=0; // show msg on error
HANDLE hEvent=NULL; // global event
HINSTANCE hASPI=NULL; // aspi lib
READFUNC pReadFunc=NULL; // read func
DEINITFUNC pDeInitFunc=NULL; // deinit func
int iInterfaceMode=1; // interface (aspi/ioctrlscsi/ioctrlraw)
int iWantedBlockSize=2352;
int iUsedBlockSize=2352;
int iUsedMode=CDVD_MODE_2352;
int iBlockDump=0;
DWORD (*pGetASPI32SupportInfo)(void); // ptrs to aspi funcs
DWORD (*pSendASPI32Command)(LPSRB);
/////////////////////////////////////////////////////////
void addr2time(unsigned long addr, unsigned char *time)
{
addr+=150;
time[3] = (unsigned char)(addr%75);
addr/=75;
time[2]=(unsigned char)(addr%60);
addr/=60;
time[1]=(unsigned char)(addr%100);
time[0]=(unsigned char)(addr/100);
}
void addr2timeB(unsigned long addr, unsigned char *time)
{
time[3] = itob((unsigned char)(addr%75));
addr/=75;
time[2]=itob((unsigned char)(addr%60));
addr/=60;
time[1]=itob((unsigned char)(addr%100));
time[0]=itob((unsigned char)(addr/100));
}
unsigned long time2addr(unsigned char *time)
{
unsigned long addr;
addr = time[0]*100;
addr += time[1];
addr *= 60;
addr = (addr + time[2])*75;
addr += time[3];
addr -= 150;
return addr;
}
unsigned long time2addrB(unsigned char *time)
{
unsigned long addr;
addr = (btoi(time[0]))*100;
addr += btoi(time[1]);
addr *= 60;
addr = (addr + btoi(time[2]))*75;
addr += btoi(time[3]);
addr -= 150;
return addr;
}
#ifndef _GCC
#ifdef __x86_64__
unsigned long reOrder(unsigned long value)
{
return ((value&0xff)<<24)|((value&0xff00)<<8)|((value&0xff0000)>>8)|(value>>24);
}
#else
unsigned long reOrder(unsigned long value)
{
#pragma warning (disable: 4035)
__asm
{
mov eax,value
bswap eax
}
}
#endif
#endif
/////////////////////////////////////////////////////////
void CreateGenEvent(void)
{
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
}
/////////////////////////////////////////////////////////
void FreeGenEvent(void)
{
if(hEvent) CloseHandle(hEvent);
hEvent=0;
}
/////////////////////////////////////////////////////////
DWORD WaitGenEvent(DWORD dwMS)
{
if(hASPI) // aspi event
return WaitForSingleObject(hEvent,dwMS);
else
{ // ioctl overlapped (always waiting til finished, dwMS not used)
DWORD dwR=0;
GetOverlappedResult(hIOCTL,&ovcIOCTL,&dwR,TRUE);
return 0;
}
}
/////////////////////////////////////////////////////////
void LockGenCDAccess(void)
{
if(hReadThread) // thread mode?
WaitForSingleObject(hThreadMutex[0],INFINITE); // -> wait until all reading is done
else // async prefetch?
if(bDoWaiting) // -> async operation has to finish first
{WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;}
}
/////////////////////////////////////////////////////////
void UnlockGenCDAccess(void)
{
if(hReadThread) // thread mode?
ReleaseMutex(hThreadMutex[0]); // -> we are finished with our special command, now reading can go on
}
/////////////////////////////////////////////////////////
void WaitUntilDriveIsReady(void)
{
if(iNoWait==0)
{
while(TestSCSIUnitReady()==0) Sleep(500);
}
}
/////////////////////////////////////////////////////////
void SetGenCDSpeed(int iReset)
{
if(iUseSpeedLimit)
{
if(bDoWaiting) // still a command running? wait
{WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;}
if(iReset) SetSCSISpeed(0xFFFF);
else
if(SetSCSISpeed(176*iSpeedLimit)<=0)
{
MessageBox(GetActiveWindow(),
"Failure: cannot change the drive speed!",
"cdvdPeops... speed limitation",
MB_OK|MB_ICONEXCLAMATION);
iUseSpeedLimit=0;
}
}
}
/////////////////////////////////////////////////////////
// checks, which direct subchannel reading type is supported
void GetBESubReadFunc(void)
{
unsigned char * pB=(unsigned char *)malloc(4096);
pReadFunc = ReadSCSI_BE_Sub; // pre-init read func
WaitUntilDriveIsReady(); // wait before first read
ReadSub_BE_2(0,pB,1); // first (unchecked) read
if(!ReadSub_BE_2(0,pB,1)) // read again, and check this time
{ // -> read failed?
if(ReadSub_BE_2_1(0,pB,1)) // -> try different sub reading
{ // --> success? mmm... let us check the data
DecodeSub_BE_2_1(pB+2352); // --> decode sub
if(*(pB+2352)==0x41) // --> check the first decoded byte
pReadFunc = ReadSCSI_BE_Sub_1; // ---> wow, byte is ok
}
}
free(pB);
}
/////////////////////////////////////////////////////////
int GetGenReadFunc(int iRM)
{
switch(iRM) // scsi read mode
{
// ------------------------------------------------ //
case MODE_BE_1:
case MODE_BE_2:
{
if(iUseSubReading==1)
GetBESubReadFunc();
else pReadFunc = ReadSCSI_BE;
} break;
// ------------------------------------------------ //
case MODE_28_1:
case MODE_28_2:
{
if(iUseSubReading==1)
pReadFunc = ReadSCSI_28_Sub;
else pReadFunc = ReadSCSI_28;
} break;
// ------------------------------------------------ //
case MODE_28_2048:
{
pReadFunc = ReadSCSI_28_2048;
} break;
// ------------------------------------------------ //
case MODE_28_2048_Ex:
{
pReadFunc = ReadSCSI_28_2048_Ex;
} break;
// ------------------------------------------------ //
default:
{
pReadFunc = ReadSCSI_Dummy;
} return -3;
// ------------------------------------------------ //
}
return 1;
}
/////////////////////////////////////////////////////////
int OpenGenCD(int iA,int iT,int iL)
{
pDeInitFunc = NULL; // init de-init func
pReadFunc = ReadSCSI_Dummy; // init (dummy) read func
if(iA==-1) return -1; // not configured properly
// -------------------------------------------------- //
if(iInterfaceMode>1) // ioctrl interfaces?
{
OpenIOCTLHandle(iA,iT,iL); // open w2k/xp ioctrl device
if(hIOCTL==NULL) return -2; // no cdrom available
if(iInterfaceMode==3) // special ioctl RAW mode?
{ // -> get special reading funcs (non-scsi!)
if(iUseSubReading==1)
pReadFunc = ReadIOCTL_Raw_Sub;
else pReadFunc = ReadIOCTL_Raw;
WaitUntilDriveIsReady();
return 1;
}
}
else // aspi interface?
{
int iDevice=GetSCSIDevice(iA,iT,iL); // get device type
if(iDevice!=DTYPE_CDROM) return -2; // no cdrom? bye
}
if(CheckSCSIReadMode()==SS_COMP)
WaitUntilDriveIsReady();
else
{
CloseIOCTLHandle();
return -3;
}
return 1;
}
/////////////////////////////////////////////////////////
void CloseGenCD(void)
{
iCDROK=0; // no more cd available
if(pDeInitFunc) pDeInitFunc(); // deinit, if needed
pDeInitFunc = NULL;
pReadFunc = ReadSCSI_Dummy;
CloseIOCTLHandle(); // close ioctl drive file (if used)
}
/////////////////////////////////////////////////////////
void OpenGenInterface(void)
{
hASPI=NULL;
if(iInterfaceMode==0) return; // no interface? no fun
else
if(iInterfaceMode==1) // aspi
{
hASPI=LoadLibrary("WNASPI32.DLL");
if(hASPI)
{
pGetASPI32SupportInfo =
(DWORD(*)(void)) GetProcAddress(hASPI,"GetASPI32SupportInfo");
pSendASPI32Command =
(DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
if(!pGetASPI32SupportInfo || !pSendASPI32Command)
{
iInterfaceMode=0;
return;
}
}
}
else // ioctl
{
if(iInterfaceMode<2 || iInterfaceMode>3) iInterfaceMode=2;
pGetASPI32SupportInfo = NULL;
pSendASPI32Command = IOCTLSendASPI32Command;
}
}
/////////////////////////////////////////////////////////
void CloseGenInterface(void)
{
pGetASPI32SupportInfo=NULL; // clear funcs
pSendASPI32Command=NULL;
if(hASPI) // free aspi
{
FreeLibrary(hASPI);
hASPI=NULL;
}
else CloseIOCTLHandle(); // or close ioctl file
}
/////////////////////////////////////////////////////////
int GetGenCDDrives(char * pDList)
{
if(hASPI) return GetSCSICDDrives(pDList); // aspi? use it
return GetIOCTLCDDrives(pDList); // or use ioctl
}
/////////////////////////////////////////////////////////