mirror of https://github.com/PCSX2/pcsx2.git
387 lines
12 KiB
C
387 lines
12 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
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////
|