cdrom interfaces
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@717
This commit is contained in:
parent
d4af8d8889
commit
cfd4de316e
3 changed files with 1383 additions and 0 deletions
773
src/dos/cdrom.cpp
Normal file
773
src/dos/cdrom.cpp
Normal file
|
@ -0,0 +1,773 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
*
|
||||
* 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 Library 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.
|
||||
*/
|
||||
|
||||
// ASPI support for WIN32 CDROM
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <string.h>
|
||||
#include "cdrom.h"
|
||||
#include "scsidefs.h" // Aspi stuff
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
CDROM_Interface_Aspi::CDROM_Interface_Aspi(void)
|
||||
{
|
||||
hASPI = NULL;
|
||||
hEvent = NULL;
|
||||
pGetASPI32SupportInfo = NULL;
|
||||
pSendASPI32Command = NULL;
|
||||
};
|
||||
|
||||
CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void)
|
||||
{
|
||||
// Stop Audio
|
||||
StopAudio();
|
||||
|
||||
pGetASPI32SupportInfo = NULL; // clear funcs
|
||||
pSendASPI32Command = NULL;
|
||||
|
||||
if (hASPI) { // free aspi
|
||||
FreeLibrary(hASPI);
|
||||
hASPI=NULL;
|
||||
}
|
||||
};
|
||||
|
||||
bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize)
|
||||
// hKey has to be open
|
||||
{
|
||||
// Read subkey
|
||||
ULONG valType;
|
||||
ULONG result;
|
||||
result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize);
|
||||
return (result == ERROR_SUCCESS);
|
||||
};
|
||||
|
||||
BYTE CDROM_Interface_Aspi::GetHostAdapter(void)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
BYTE buffer[40];
|
||||
|
||||
for (int i=0; i<255; i++) {
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
memset(&s,0,sizeof(s));
|
||||
// Check Media test...
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = i;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_BufLen = 40;
|
||||
s.SRB_BufPointer = (BYTE FAR*)buffer;
|
||||
s.SRB_CDBLen = 14;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = 0x4A;
|
||||
s.CDBByte[1] = (lun<<5)|1; // lun & immediate
|
||||
s.CDBByte[4] = 0x10; // media
|
||||
s.CDBByte[8] = 40;
|
||||
ResetEvent(hEvent);
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
if ((dwStatus==0) && (s.SRB_Status!=SS_INVALID_CMD)) {
|
||||
DEBUG_ShowMsg(0,"SCSI: Host Adapter found: %d",i);
|
||||
return i;
|
||||
};
|
||||
};
|
||||
DEBUG_ShowMsg(0,"SCSI: Host Adapter not found.");
|
||||
return 0;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
|
||||
// hKey has to be open
|
||||
{
|
||||
FILETIME time;
|
||||
ULONG result,newKeyResult;
|
||||
char subKey[256];
|
||||
char buffer[256];
|
||||
ULONG bufferSize = 256;
|
||||
ULONG subKeySize = 256;
|
||||
HKEY hNewKey;
|
||||
|
||||
ULONG index = 0;
|
||||
do {
|
||||
result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
|
||||
if (result==ERROR_SUCCESS) {
|
||||
// Open Key...
|
||||
newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
|
||||
if (newKeyResult==ERROR_SUCCESS) {
|
||||
if (GetRegistryValue(hNewKey,"CurrentDriveLetterAssignment",buffer,256)) {
|
||||
DEBUG_ShowMsg(0,"SCSI: Drive Letter found: %s",buffer);
|
||||
// aha, something suspicious...
|
||||
if (buffer[0]==letter) {
|
||||
// found it... lets see if we can get the scsi values
|
||||
bool v1 = GetRegistryValue(hNewKey,"SCSILUN",buffer,256);
|
||||
DEBUG_ShowMsg(0,"SCSI: SCSILUN found: %s",buffer);
|
||||
lun = buffer[0]-'0';
|
||||
bool v2 = GetRegistryValue(hNewKey,"SCSITargetID",buffer,256);
|
||||
DEBUG_ShowMsg(0,"SCSI: SCSITargetID found: %s",buffer);
|
||||
target = buffer[0]-'0';
|
||||
RegCloseKey(hNewKey);
|
||||
if (v1 && v2) {
|
||||
haId = GetHostAdapter();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
RegCloseKey(hNewKey);
|
||||
};
|
||||
index++;
|
||||
} while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::ScanRegistry(HKEY& hKeyBase)
|
||||
// hKey has to be open
|
||||
{
|
||||
FILETIME time;
|
||||
ULONG result,newKeyResult;
|
||||
char subKey[256];
|
||||
ULONG subKeySize= 256;
|
||||
HKEY hNewKey;
|
||||
|
||||
ULONG index = 0;
|
||||
do {
|
||||
result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
|
||||
if ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA)) {
|
||||
// Open Key...
|
||||
newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
|
||||
if (newKeyResult==ERROR_SUCCESS) {
|
||||
bool found = ScanRegistryFindKey(hNewKey);
|
||||
RegCloseKey(hNewKey);
|
||||
if (found) return true;
|
||||
};
|
||||
RegCloseKey(hNewKey);
|
||||
};
|
||||
index++;
|
||||
} while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::SetDevice(char* path)
|
||||
{
|
||||
// load WNASPI32.DLL
|
||||
hASPI = LoadLibrary ( "WNASPI32.DLL" );
|
||||
if (!hASPI) return false;
|
||||
// Get Pointer to ASPI funcs
|
||||
pGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hASPI,"GetASPI32SupportInfo");
|
||||
pSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
|
||||
if (!pGetASPI32SupportInfo || !pSendASPI32Command) return false;
|
||||
// Letter
|
||||
letter = toupper(path[0]);
|
||||
|
||||
// Check OS
|
||||
OSVERSIONINFO osi;
|
||||
osi.dwOSVersionInfoSize = sizeof(osi);
|
||||
GetVersionEx(&osi);
|
||||
if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
|
||||
if (GetDriveType(path)==DRIVE_CDROM) {
|
||||
// WIN XP/NT/2000
|
||||
int iDA,iDT,iDL;
|
||||
letter = path[0];
|
||||
HANDLE hF = OpenIOCTLFile(letter,FALSE);
|
||||
GetIOCTLAdapter(hF,&iDA,&iDT,&iDL);
|
||||
CloseHandle(hF);
|
||||
// Set SCSI IDs
|
||||
haId = iDA;
|
||||
target = iDT;
|
||||
lun = iDL;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// win 95/98/ME have to scan the registry...
|
||||
// lets hope the layout is always the same... i dunno...
|
||||
char key[2048];
|
||||
HKEY hKeyBase;
|
||||
bool found = false;
|
||||
strcpy(key,"ENUM\\SCSI");
|
||||
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) {
|
||||
found = ScanRegistry(hKeyBase);
|
||||
};
|
||||
RegCloseKey(hKeyBase);
|
||||
return found;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut)
|
||||
{
|
||||
TOC toc;
|
||||
if (GetTOC((LPTOC)&toc) == SS_COMP) {
|
||||
stTrack = toc.cFirstTrack;
|
||||
endTrack = toc.cLastTrack;
|
||||
leadOut.min = (unsigned char)(toc.tracks[endTrack].lAddr >> 8) &0xFF;
|
||||
leadOut.sec = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF;
|
||||
leadOut.fr = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
|
||||
{
|
||||
TOC toc;
|
||||
if (GetTOC((LPTOC)&toc) == SS_COMP) {
|
||||
start.min = (unsigned char)(toc.tracks[track-1].lAddr >> 8) &0xFF;
|
||||
start.sec = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF;
|
||||
start.fr = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF;
|
||||
attr = toc.tracks[track-1].cAdrCtrl;
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync)
|
||||
{
|
||||
HANDLE hF;
|
||||
char szFName[16];
|
||||
OSVERSIONINFO ov;
|
||||
DWORD dwFlags;
|
||||
DWORD dwIOCTLAttr;
|
||||
// if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED;
|
||||
// else
|
||||
dwIOCTLAttr=0;
|
||||
|
||||
memset(&ov,0,sizeof(OSVERSIONINFO));
|
||||
ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&ov);
|
||||
|
||||
if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4))
|
||||
dwFlags = GENERIC_READ|GENERIC_WRITE; // add gen write on W2k/XP
|
||||
else
|
||||
dwFlags = GENERIC_READ;
|
||||
|
||||
wsprintf(szFName, "\\\\.\\%c:",cLetter);
|
||||
|
||||
hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // open drive
|
||||
NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
|
||||
|
||||
if (hF==INVALID_HANDLE_VALUE) {
|
||||
dwFlags^=GENERIC_WRITE; // mmm... no success
|
||||
hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again
|
||||
NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
|
||||
if (hF==INVALID_HANDLE_VALUE) return NULL;
|
||||
}
|
||||
return hF;
|
||||
}
|
||||
|
||||
void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL)
|
||||
{
|
||||
char szBuf[1024];
|
||||
PSCSI_ADDRESS pSA;
|
||||
DWORD dwRet;
|
||||
|
||||
*iDA=*iDT=*iDL=-1;
|
||||
if(hF==NULL) return;
|
||||
|
||||
memset(szBuf,0,1024);
|
||||
|
||||
pSA=(PSCSI_ADDRESS)szBuf;
|
||||
pSA->Length=sizeof(SCSI_ADDRESS);
|
||||
|
||||
if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL,
|
||||
0,pSA,sizeof(SCSI_ADDRESS),
|
||||
&dwRet,NULL))
|
||||
return;
|
||||
|
||||
*iDA = pSA->PortNumber;
|
||||
*iDT = pSA->TargetId;
|
||||
*iDL = pSA->Lun;
|
||||
}
|
||||
|
||||
DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = sizeof(*toc);
|
||||
s.SRB_BufPointer = (BYTE FAR *)toc;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 0x0A;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = 0x43;
|
||||
s.CDBByte[1] = 0x02; // 0x02 for MSF
|
||||
s.CDBByte[7] = 0x03;
|
||||
s.CDBByte[8] = 0x24;
|
||||
|
||||
ResetEvent(hEvent);
|
||||
dwStatus=pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
|
||||
|
||||
return (s.SRB_Status==SS_COMP);
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = 0;
|
||||
s.SRB_BufPointer = 0;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 12;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0xa5;
|
||||
s.CDBByte[1] = lun << 5;
|
||||
s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
|
||||
s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
|
||||
s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
|
||||
s.CDBByte[5] = (unsigned char)((start & 0xFF));
|
||||
s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
|
||||
s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
|
||||
s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
|
||||
s.CDBByte[9] = (unsigned char)(len & 0xFF);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000);
|
||||
|
||||
return s.SRB_Status==SS_COMP;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Aspi::StopAudio(void)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = 0x00;
|
||||
s.SRB_SenseLen = 0x0E;
|
||||
s.SRB_CDBLen = 0x0A;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = 0x4E;
|
||||
|
||||
ResetEvent(hEvent);
|
||||
dwStatus=pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::PauseAudio(bool resume)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = 0x00;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 0x0A;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = 0x4B;
|
||||
s.CDBByte[8] = (unsigned char)resume; // Pause
|
||||
|
||||
ResetEvent(hEvent);
|
||||
dwStatus=pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
SUB_Q_CURRENT_POSITION pos;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(pos);
|
||||
s.SRB_BufPointer = (BYTE FAR *)&pos;
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0x42;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x40; // subq
|
||||
s.CDBByte[3] = 0x01; // curr pos info
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(pos);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
attr = (pos.ADR<<4) | pos.Control;
|
||||
track = pos.TrackNumber;
|
||||
index = pos.IndexNumber;
|
||||
absPos.min = pos.AbsoluteAddress[1];
|
||||
absPos.sec = pos.AbsoluteAddress[2];
|
||||
absPos.fr = pos.AbsoluteAddress[3];
|
||||
relPos.min = pos.TrackRelativeAddress[1];
|
||||
relPos.sec = pos.TrackRelativeAddress[2];
|
||||
relPos.fr = pos.TrackRelativeAddress[3];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
|
||||
{
|
||||
SUB_Q_MEDIA_CATALOG_NUMBER upc;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(upc);
|
||||
s.SRB_BufPointer = (BYTE FAR *)&upc;
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0x42;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x40; // subq
|
||||
s.CDBByte[3] = 0x02; // get upc
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(upc);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
// attr = (upc.ADR<<4) | upc.Control;
|
||||
attr = 0;
|
||||
int pos = 0;
|
||||
// Convert to mscdex format
|
||||
// for (int i=0; i<6; i++) upcdata[i] = (upc.MediaCatalog[pos++]<<4)+(upc.MediaCatalog[pos++]&0x0F);
|
||||
// upcdata[6] = (upc.MediaCatalog[pos++]<<4);
|
||||
for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
|
||||
{
|
||||
playing = pause = false;
|
||||
|
||||
SUB_Q_HEADER sub;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(sub);
|
||||
s.SRB_BufPointer = (BYTE FAR *)⊂
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0x42;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x00; // no subq
|
||||
s.CDBByte[3] = 0x00; // dont care
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(sub);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
playing = (sub.AudioStatus==0x11);
|
||||
pause = (sub.AudioStatus==0x12);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = 0;
|
||||
s.SRB_BufPointer = 0;
|
||||
s.SRB_CDBLen = 14;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0x1B;
|
||||
s.CDBByte[1] = (lun<<5)|1; // lun & immediate
|
||||
s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
|
||||
{
|
||||
mediaPresent = mediaChanged = trayOpen = false;
|
||||
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
BYTE buffer[40];
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = 40;
|
||||
s.SRB_BufPointer = (BYTE FAR*)buffer;
|
||||
s.SRB_CDBLen = 14;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0x4A;
|
||||
s.CDBByte[1] = (lun<<5)|1; // lun & immediate
|
||||
s.CDBByte[4] = 0x10; // media
|
||||
s.CDBByte[8] = 40;
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
mediaChanged = (buffer[0x04]== 0x04);
|
||||
mediaPresent = (buffer[0x05] & 0x02)>0;
|
||||
trayOpen = (buffer[0x05] & 0x01)>0;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
// FIXME : Is there a method to get cooked sectors with aspi ???
|
||||
// all combination i tried were failing.
|
||||
// so we have to allocate extra mem and copy data to buffer if in cooked mode
|
||||
char* inPtr = (char*)buffer;
|
||||
if (!raw) inPtr = new char[num*2352];
|
||||
if (!inPtr) return false;
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = 2352*num; //num*(raw?2352:2048);
|
||||
s.SRB_BufPointer = (BYTE FAR*)inPtr;
|
||||
s.SRB_CDBLen = 12;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0xBE;
|
||||
s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
|
||||
s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
|
||||
s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
|
||||
s.CDBByte[5] = (unsigned char)((sector & 0xFF));
|
||||
s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
|
||||
s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
|
||||
s.CDBByte[8] = (unsigned char) (num & 0xFF);
|
||||
s.CDBByte[9] = (raw?0xF0:0x10);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
dwStatus = pSendASPI32Command((LPSRB)&s);
|
||||
|
||||
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) {
|
||||
if (!raw) delete[] inPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!raw) {
|
||||
// copy user data to buffer
|
||||
char* source = inPtr;
|
||||
source+=16; // jump 16 bytes
|
||||
char* outPtr = (char*)buffer;
|
||||
for (unsigned long i=0; i<num; i++) {
|
||||
memcpy(outPtr,source,2048);
|
||||
outPtr+=COOKED_SECTOR_SIZE;
|
||||
source+=RAW_SECTOR_SIZE;
|
||||
};
|
||||
delete[] inPtr;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
int CDROM_GetMountType(char* path)
|
||||
// 0 - physical CDROM
|
||||
// 1 - Iso file
|
||||
// 2 - subdirectory
|
||||
{
|
||||
// 1. Smells like a real cdrom
|
||||
if ((strlen(path)<=3) && (path[2]=='\\') && (strchr(path,'\\')==strrchr(path,'\\')) && (GetDriveType(path)==DRIVE_CDROM)) return 0;
|
||||
// 2. Iso file ?
|
||||
// FIXME : How to detect them ?
|
||||
// return 1;
|
||||
// 3. bah, ordinary directory
|
||||
return 2;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include "cdrom.h"
|
||||
|
||||
#endif
|
||||
|
||||
// ******************************************************
|
||||
// Fake CDROM
|
||||
// ******************************************************
|
||||
|
||||
bool CDROM_Interface_Fake :: GetAudioTracks (int& stTrack, int& end, TMSF& leadOut)
|
||||
{
|
||||
stTrack = end = 1;
|
||||
leadOut.min = 60;
|
||||
leadOut.sec = leadOut.fr = 0;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Fake :: GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
|
||||
{
|
||||
if (track>1) return false;
|
||||
start.min = start.fr = 0;
|
||||
start.sec = 2;
|
||||
attr = 0x60; // data / permitted
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Fake :: GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
attr = 0;
|
||||
track = index = 1;
|
||||
relPos.min = relPos.fr = 0; relPos.sec = 2;
|
||||
absPos.min = absPos.fr = 0; absPos.sec = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Fake :: GetAudioStatus (bool& playing, bool& pause)
|
||||
{
|
||||
playing = pause = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Fake :: GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
|
||||
{
|
||||
mediaPresent = true;
|
||||
mediaChanged = false;
|
||||
trayOpen = false;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
179
src/dos/cdrom.h
Normal file
179
src/dos/cdrom.h
Normal file
|
@ -0,0 +1,179 @@
|
|||
|
||||
#ifndef __CDROM_INTERFACE__
|
||||
#define __CDROM_INTERFACE__
|
||||
|
||||
#define MAX_ASPI_CDROM 5
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define RAW_SECTOR_SIZE 2352
|
||||
#define COOKED_SECTOR_SIZE 2048
|
||||
|
||||
typedef struct SMSF {
|
||||
unsigned char min;
|
||||
unsigned char sec;
|
||||
unsigned char fr;
|
||||
} TMSF;
|
||||
|
||||
extern int CDROM_GetMountType(char* path);
|
||||
|
||||
class CDROM_Interface
|
||||
{
|
||||
public:
|
||||
// CDROM_Interface (void);
|
||||
virtual ~CDROM_Interface (void) {};
|
||||
|
||||
virtual bool SetDevice (char* path) = 0;
|
||||
|
||||
virtual bool GetUPC (unsigned char& attr, char* upc) = 0;
|
||||
|
||||
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0;
|
||||
virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) = 0;
|
||||
virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0;
|
||||
virtual bool GetAudioStatus (bool& playing, bool& pause) = 0;
|
||||
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
|
||||
|
||||
virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0;
|
||||
virtual bool PauseAudio (bool resume) = 0;
|
||||
virtual bool StopAudio (void) = 0;
|
||||
|
||||
virtual bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) = 0;
|
||||
|
||||
virtual bool LoadUnloadMedia (bool unload) = 0;
|
||||
};
|
||||
|
||||
class CDROM_Interface_Fake : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
bool SetDevice (char* path) { return true; };
|
||||
bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len) { return true; };
|
||||
bool PauseAudio (bool resume) { return true; };
|
||||
bool StopAudio (void) { return true; };
|
||||
bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) { return true; };
|
||||
bool LoadUnloadMedia (bool unload) { return true; };
|
||||
};
|
||||
|
||||
|
||||
#if defined (WIN32) /* Win 32 */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <windows.h>
|
||||
#include "wnaspi32.h" // Aspi stuff
|
||||
|
||||
class CDROM_Interface_Aspi : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_Aspi (void);
|
||||
~CDROM_Interface_Aspi (void);
|
||||
|
||||
bool SetDevice (char* path);
|
||||
|
||||
bool GetUPC (unsigned char& attr, char* upc);
|
||||
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
bool PauseAudio (bool resume);
|
||||
bool StopAudio (void);
|
||||
|
||||
bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num);
|
||||
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
|
||||
private:
|
||||
DWORD GetTOC (LPTOC toc);
|
||||
HANDLE OpenIOCTLFile (char cLetter, BOOL bAsync);
|
||||
void GetIOCTLAdapter (HANDLE hF,int * iDA,int * iDT,int * iDL);
|
||||
bool ScanRegistryFindKey (HKEY& hKeyBase);
|
||||
bool ScanRegistry (HKEY& hKeyBase);
|
||||
BYTE GetHostAdapter (void);
|
||||
|
||||
// ASPI stuff
|
||||
BYTE haId;
|
||||
BYTE target;
|
||||
BYTE lun;
|
||||
char letter;
|
||||
|
||||
// Windows stuff
|
||||
HINSTANCE hASPI;
|
||||
HANDLE hEvent; // global event
|
||||
DWORD (*pGetASPI32SupportInfo) (void); // ptrs to aspi funcs
|
||||
DWORD (*pSendASPI32Command) (LPSRB);
|
||||
};
|
||||
|
||||
class CDROM_Interface_Ioctl : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_Ioctl (void);
|
||||
~CDROM_Interface_Ioctl (void);
|
||||
|
||||
bool SetDevice (char* path);
|
||||
|
||||
bool GetUPC (unsigned char& attr, char* upc);
|
||||
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
bool PauseAudio (bool resume);
|
||||
bool StopAudio (void);
|
||||
|
||||
bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num);
|
||||
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
|
||||
private:
|
||||
|
||||
HANDLE hIOCTL;
|
||||
TMSF oldLeadOut;
|
||||
};
|
||||
|
||||
#else /* Linux */
|
||||
|
||||
class CDROM_Interface_Linux : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_Linux (void);
|
||||
~CDROM_Interface_Linux (void);
|
||||
|
||||
bool SetDevice (char* path);
|
||||
|
||||
bool GetUPC (unsigned char& attr, char* upc);
|
||||
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
bool PauseAudio (bool resume);
|
||||
bool StopAudio (void);
|
||||
|
||||
bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num);
|
||||
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
|
||||
private:
|
||||
|
||||
int dhandle;
|
||||
TMSF oldLeadOut;
|
||||
};
|
||||
|
||||
#endif /* linux */
|
||||
|
||||
#endif /* __CDROM_INTERFACE__ */
|
431
src/dos/cdrom_ioctl.cpp
Normal file
431
src/dos/cdrom_ioctl.cpp
Normal file
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
*
|
||||
* 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 Library 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.
|
||||
*/
|
||||
|
||||
// IOCTL support for linux CDROM
|
||||
|
||||
#if __linux__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/cdrom.h>
|
||||
|
||||
#include "cdrom.h"
|
||||
|
||||
CDROM_Interface_Linux::CDROM_Interface_Linux(void)
|
||||
{
|
||||
memset(&oldLeadOut,0,sizeof(oldLeadOut));
|
||||
};
|
||||
|
||||
CDROM_Interface_Linux::~CDROM_Interface_Linux(void)
|
||||
{
|
||||
// Stop Audio, if neccessary
|
||||
StopAudio();
|
||||
close(dhandle);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::SetDevice(char* path)
|
||||
{
|
||||
dhandle = open(path,O_RDONLY|O_NONBLOCK);
|
||||
return (dhandle>=0);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut)
|
||||
{
|
||||
struct cdrom_tochdr header;
|
||||
|
||||
/* read the header information */
|
||||
if (ioctl(dhandle, CDROMREADTOCHDR, &header) != 0) return false;
|
||||
|
||||
/* store the resulting information */
|
||||
stTrack = header.cdth_trk0; /* you can assume this to be zero */
|
||||
endTrack = header.cdth_trk1;
|
||||
|
||||
/* Get the leadout track */
|
||||
struct cdrom_tocentry entry;
|
||||
|
||||
entry.cdte_track = CDROM_LEADOUT; /* find the address of the leadout track */
|
||||
entry.cdte_format = CDROM_MSF; /* choose MSF addressing */
|
||||
|
||||
if (ioctl(dhandle, CDROMREADTOCENTRY,&entry)!=0) return false;
|
||||
|
||||
leadOut.min = entry.cdte_addr.msf.minute;
|
||||
leadOut.sec = entry.cdte_addr.msf.second;
|
||||
leadOut.fr = entry.cdte_addr.msf.frame;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
|
||||
{
|
||||
struct cdrom_tocentry entry;
|
||||
|
||||
entry.cdte_track = track; /* find the address of the first track */
|
||||
entry.cdte_format = CDROM_MSF; /* choose MSF addressing */
|
||||
|
||||
if (ioctl(dhandle, CDROMREADTOCENTRY,&entry)!=0) return false;
|
||||
|
||||
/* attribtute */
|
||||
attr = (entry.cdte_adr<<4) | entry.cdte_ctrl;
|
||||
/* store the address information */
|
||||
start.min = entry.cdte_addr.msf.minute;
|
||||
start.sec = entry.cdte_addr.msf.second;
|
||||
start.fr = entry.cdte_addr.msf.frame;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::PlayAudioSector(unsigned long start,unsigned long len)
|
||||
{
|
||||
struct cdrom_blk addr;
|
||||
addr.from = start;
|
||||
addr.len = len;
|
||||
return (ioctl(dhandle, CDROMPLAYBLK, &addr)==0);
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Linux::StopAudio(void)
|
||||
{
|
||||
return (ioctl(dhandle,CDROMSTOP,0)==0);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::PauseAudio(bool resume)
|
||||
{
|
||||
if (resume) return (ioctl(dhandle, CDROMRESUME,0)==0);
|
||||
else return (ioctl(dhandle, CDROMPAUSE,0)==0);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
struct cdrom_subchnl sub;
|
||||
|
||||
sub.cdsc_format = CDROM_MSF;
|
||||
if (ioctl(dhandle, CDROMSUBCHNL, &sub)!=0) return false;
|
||||
|
||||
/* attribute */
|
||||
attr = (sub.cdsc_adr<<4) | sub.cdsc_ctrl;
|
||||
track = sub.cdsc_trk;
|
||||
index = sub.cdsc_ind;
|
||||
relPos.fr = sub.cdsc_absaddr.msf.frame;
|
||||
relPos.sec = sub.cdsc_absaddr.msf.second;
|
||||
relPos.min = sub.cdsc_absaddr.msf.minute;
|
||||
absPos.fr = sub.cdsc_reladdr.msf.frame;
|
||||
absPos.sec = sub.cdsc_reladdr.msf.second;
|
||||
absPos.min = sub.cdsc_reladdr.msf.minute;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetUPC(unsigned char& attr, char* upcdata)
|
||||
{
|
||||
return (ioctl(dhandle, CDROM_GET_UPC, (void*)upcdata)==0);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetAudioStatus(bool& playing, bool& pause)
|
||||
{
|
||||
struct cdrom_subchnl sub;
|
||||
|
||||
sub.cdsc_format = CDROM_MSF;
|
||||
if (ioctl(dhandle, CDROMSUBCHNL, &sub)!=0) return false;
|
||||
|
||||
playing = (sub.cdsc_audiostatus==CDROM_AUDIO_PLAY);
|
||||
pause = (sub.cdsc_audiostatus==CDROM_AUDIO_PAUSED);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::LoadUnloadMedia(bool unload)
|
||||
{
|
||||
return (ioctl(dhandle, CDROMEJECT,0)==0);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
|
||||
{
|
||||
// Seems not possible to get this values using ioctl...
|
||||
int track1,track2;
|
||||
TMSF leadOut;
|
||||
// If we can read, there's a media
|
||||
mediaPresent = GetAudioTracks(track1, track2, leadOut);
|
||||
trayOpen = !mediaPresent;
|
||||
mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
|
||||
// Save old values
|
||||
oldLeadOut.min = leadOut.min;
|
||||
oldLeadOut.sec = leadOut.sec;
|
||||
oldLeadOut.fr = leadOut.fr;
|
||||
// always success
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Linux::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num)
|
||||
{
|
||||
// FIXME: ToDo
|
||||
return false;
|
||||
};
|
||||
|
||||
int CDROM_GetMountType(char* path)
|
||||
// 0 - physical CDROM
|
||||
// 1 - Iso file
|
||||
// 2 - subdirectory
|
||||
{
|
||||
// 1. Smells like a real cdrom
|
||||
// FIXME: Better check if drive is a cdrom
|
||||
if ((strchr(path,'/')==strrchr(path,'/')) && strstr(path,"cdrom")) return 0;
|
||||
// 2. Iso file ?
|
||||
// FIXME : How to detect them ?
|
||||
// return 1;
|
||||
// 3. bah, ordinary directory
|
||||
return 2;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// *****************************************************************
|
||||
// Windows IOCTL functions (not suitable for 95/98/Me)
|
||||
// *****************************************************************
|
||||
|
||||
#include "cdrom.h"
|
||||
#include <winioctl.h> // Ioctl stuff
|
||||
#include "ntddcdrm.h" // Ioctl stuff
|
||||
|
||||
CDROM_Interface_Ioctl::CDROM_Interface_Ioctl()
|
||||
{
|
||||
hIOCTL = INVALID_HANDLE_VALUE;
|
||||
memset(&oldLeadOut,0,sizeof(oldLeadOut));
|
||||
};
|
||||
|
||||
CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl()
|
||||
{
|
||||
StopAudio();
|
||||
CloseHandle(hIOCTL);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc)
|
||||
{
|
||||
// FIXME : To Do
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut)
|
||||
{
|
||||
CDROM_TOC toc;
|
||||
DWORD byteCount;
|
||||
BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0,
|
||||
&toc, sizeof(toc), &byteCount,NULL);
|
||||
if (!bStat) return false;
|
||||
|
||||
stTrack = toc.FirstTrack;
|
||||
endTrack = toc.LastTrack;
|
||||
leadOut.min = toc.TrackData[endTrack].Address[1];
|
||||
leadOut.sec = toc.TrackData[endTrack].Address[2];
|
||||
leadOut.fr = toc.TrackData[endTrack].Address[3];
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr)
|
||||
{
|
||||
CDROM_TOC toc;
|
||||
DWORD byteCount;
|
||||
BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0,
|
||||
&toc, sizeof(toc), &byteCount,NULL);
|
||||
if (!bStat) return false;
|
||||
|
||||
attr = (toc.TrackData[track-1].Adr << 4) | toc.TrackData[track].Control;
|
||||
start.min = toc.TrackData[track-1].Address[1];
|
||||
start.sec = toc.TrackData[track-1].Address[2];
|
||||
start.fr = toc.TrackData[track-1].Address[3];
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
CDROM_SUB_Q_DATA_FORMAT insub;
|
||||
SUB_Q_CHANNEL_DATA sub;
|
||||
DWORD byteCount;
|
||||
|
||||
insub.Format = IOCTL_CDROM_CURRENT_POSITION;
|
||||
|
||||
BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub),
|
||||
&sub, sizeof(sub), &byteCount,NULL);
|
||||
if (!bStat) return false;
|
||||
|
||||
attr = (sub.CurrentPosition.ADR << 4) | sub.CurrentPosition.Control;
|
||||
track = sub.CurrentPosition.TrackNumber;
|
||||
index = sub.CurrentPosition.IndexNumber;
|
||||
relPos.min = sub.CurrentPosition.TrackRelativeAddress[1];
|
||||
relPos.sec = sub.CurrentPosition.TrackRelativeAddress[2];
|
||||
relPos.fr = sub.CurrentPosition.TrackRelativeAddress[3];
|
||||
absPos.min = sub.CurrentPosition.AbsoluteAddress[1];
|
||||
absPos.sec = sub.CurrentPosition.AbsoluteAddress[2];
|
||||
absPos.fr = sub.CurrentPosition.AbsoluteAddress[3];
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause)
|
||||
{
|
||||
CDROM_SUB_Q_DATA_FORMAT insub;
|
||||
SUB_Q_CHANNEL_DATA sub;
|
||||
DWORD byteCount;
|
||||
|
||||
insub.Format = IOCTL_CDROM_CURRENT_POSITION;
|
||||
|
||||
BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub),
|
||||
&sub, sizeof(sub), &byteCount,NULL);
|
||||
if (!bStat) return false;
|
||||
|
||||
playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS);
|
||||
pause = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
|
||||
{
|
||||
// Seems not possible to get this values using ioctl...
|
||||
int track1,track2;
|
||||
TMSF leadOut;
|
||||
// If we can read, there's a media
|
||||
mediaPresent = GetAudioTracks(track1, track2, leadOut),
|
||||
trayOpen = !mediaPresent;
|
||||
mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
|
||||
// Save old values
|
||||
oldLeadOut.min = leadOut.min;
|
||||
oldLeadOut.sec = leadOut.sec;
|
||||
oldLeadOut.fr = leadOut.fr;
|
||||
// always success
|
||||
return true;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long len)
|
||||
{
|
||||
CDROM_PLAY_AUDIO_MSF audio;
|
||||
DWORD byteCount;
|
||||
// Start
|
||||
unsigned long addr = start + 150;
|
||||
audio.StartingF = (UCHAR)(addr%75); addr/=75;
|
||||
audio.StartingS = (UCHAR)(addr%60);
|
||||
audio.StartingM = (UCHAR)(addr/60);
|
||||
// End
|
||||
addr = start + len + 150;
|
||||
audio.EndingF = (UCHAR)(addr%75); addr/=75;
|
||||
audio.EndingS = (UCHAR)(addr%60);
|
||||
audio.EndingM = (UCHAR)(addr/60);
|
||||
|
||||
BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio),
|
||||
NULL, 0, &byteCount,NULL);
|
||||
return bStat>0;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::PauseAudio(bool resume)
|
||||
{
|
||||
BOOL bStat;
|
||||
DWORD byteCount;
|
||||
if (resume) bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO, NULL, 0,
|
||||
NULL, 0, &byteCount,NULL);
|
||||
else bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO, NULL, 0,
|
||||
NULL, 0, &byteCount,NULL);
|
||||
return bStat>0;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::StopAudio(void)
|
||||
{
|
||||
BOOL bStat;
|
||||
DWORD byteCount;
|
||||
bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0,
|
||||
NULL, 0, &byteCount,NULL);
|
||||
return bStat>0;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload)
|
||||
{
|
||||
BOOL bStat;
|
||||
DWORD byteCount;
|
||||
if (unload) bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA, NULL, 0,
|
||||
NULL, 0, &byteCount,NULL);
|
||||
else bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA, NULL, 0,
|
||||
NULL, 0, &byteCount,NULL);
|
||||
return bStat>0;
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Ioctl::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num)
|
||||
{
|
||||
// TODO : How to copy cooked without current overhead ?
|
||||
BOOL bStat;
|
||||
DWORD byteCount;
|
||||
RAW_READ_INFO in;
|
||||
char* inPtr;
|
||||
|
||||
in.DiskOffset.LowPart = sector;
|
||||
in.DiskOffset.HighPart = 0;
|
||||
in.SectorCount = num;
|
||||
in.TrackMode = CDDA;
|
||||
|
||||
if (!raw) inPtr = new char[num*RAW_SECTOR_SIZE];
|
||||
else inPtr = (char*)buffer;
|
||||
|
||||
bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in),
|
||||
inPtr, num*RAW_SECTOR_SIZE, &byteCount,NULL);
|
||||
|
||||
if (!raw) {
|
||||
char* source = inPtr;
|
||||
source+=16; // jump 16 bytes
|
||||
char* outPtr = (char*)buffer;
|
||||
for (unsigned long i=0; i<num; i++) {
|
||||
memcpy(outPtr,source,COOKED_SECTOR_SIZE);
|
||||
outPtr+=COOKED_SECTOR_SIZE;
|
||||
source+=RAW_SECTOR_SIZE;
|
||||
};
|
||||
delete[] inPtr;
|
||||
};
|
||||
|
||||
return (byteCount!=num*RAW_SECTOR_SIZE) && (bStat>0);
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Ioctl::SetDevice(char* path)
|
||||
{
|
||||
if (GetDriveType(path)==DRIVE_CDROM) {
|
||||
char buffer [256];
|
||||
char letter [3] = { 0, ':', 0 };
|
||||
letter[0] = path[0];
|
||||
strcpy(buffer,"\\\\.\\");
|
||||
strcat(buffer,letter);
|
||||
hIOCTL = CreateFile(buffer, // drive to open
|
||||
GENERIC_READ, // read access
|
||||
FILE_SHARE_READ | // share mode
|
||||
FILE_SHARE_WRITE,
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // disposition
|
||||
0, // file attributes
|
||||
NULL); // do not copy file attributes
|
||||
return (hIOCTL!=INVALID_HANDLE_VALUE);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/*
|
||||
int CDROM_GetMountType(char* path)
|
||||
// 0 - physical CDROM
|
||||
// 1 - Iso file
|
||||
// 2 - subdirectory
|
||||
{
|
||||
// 1. Smells like a real cdrom
|
||||
if ((strlen(path)<=3) && (path[2]=='\\') && (strchr(path,'\\')==strrchr(path,'\\')) && (GetDriveType(path)==DRIVE_CDROM)) return 0;
|
||||
// 2. Iso file ?
|
||||
// FIXME : How to detect them ?
|
||||
// return 1;
|
||||
// 3. bah, ordinary directory
|
||||
return 2;
|
||||
};
|
||||
*/
|
||||
#endif
|
Loading…
Add table
Reference in a new issue