From: Shamus Hammons Date: Tue, 1 Jun 2004 19:20:35 +0000 (+0000) Subject: Added function implementation ;-) X-Git-Tag: 1.0.7~23 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=53d1b77295cdb028ef192cb6e5cd4cf60b3d6813;p=virtualjaguar Added function implementation ;-) --- diff --git a/src/cdintf_linux.cpp b/src/cdintf_linux.cpp index c418df5..eeeec30 100644 --- a/src/cdintf_linux.cpp +++ b/src/cdintf_linux.cpp @@ -3,3 +3,52 @@ // // by James L. Hammons // + +// +// Linux support functions +// + + + +// +// OS specific implementation of OS agnostic functions +// + +bool CDIntfInit(void) +{ + WriteLog("CDINTF: Init unimplemented!\n"); + return false; +} + +void CDIntfDone(void) +{ +} + +bool CDIntfReadBlock(uint32 sector, uint8 * buffer) +{ + WriteLog("CDINTF: ReadBlock unimplemented!\n"); + return false; +} + +uint32 CDIntfGetNumSessions(void) +{ + // Still need relevant code here... !!! FIX !!! + return 2; +} + +void CDIntfSelectDrive(uint32 driveNum) +{ + WriteLog("CDINTF: SelectDrive unimplemented!\n"); +} + +uint32 CDIntfGetCurrentDrive(void) +{ + WriteLog("CDINTF: GetCurrentDrive unimplemented!\n"); + return 0; +} + +uint8 * CDIntfGetDriveName(uint32) +{ + WriteLog("CDINTF: GetDriveName unimplemented!\n"); + return NULL; +} diff --git a/src/cdintf_osx.cpp b/src/cdintf_osx.cpp index 1ca290e..3692e7e 100644 --- a/src/cdintf_osx.cpp +++ b/src/cdintf_osx.cpp @@ -1,5 +1,54 @@ // // OS specific CDROM interface (Mac OS X) // -// by ? +// by James L. Hammons & ? // + +// +// OS X support functions +// + + + +// +// OS specific implementation of OS agnostic functions +// + +bool CDIntfInit(void) +{ + WriteLog("CDINTF: Init unimplemented!\n"); + return false; +} + +void CDIntfDone(void) +{ +} + +bool CDIntfReadBlock(uint32 sector, uint8 * buffer) +{ + WriteLog("CDINTF: ReadBlock unimplemented!\n"); + return false; +} + +uint32 CDIntfGetNumSessions(void) +{ + // Still need relevant code here... !!! FIX !!! + return 2; +} + +void CDIntfSelectDrive(uint32 driveNum) +{ + WriteLog("CDINTF: SelectDrive unimplemented!\n"); +} + +uint32 CDIntfGetCurrentDrive(void) +{ + WriteLog("CDINTF: GetCurrentDrive unimplemented!\n"); + return 0; +} + +uint8 * CDIntfGetDriveName(uint32) +{ + WriteLog("CDINTF: GetDriveName unimplemented!\n"); + return NULL; +} diff --git a/src/cdintf_win32.cpp b/src/cdintf_win32.cpp index b075af5..405f689 100644 --- a/src/cdintf_win32.cpp +++ b/src/cdintf_win32.cpp @@ -3,410 +3,450 @@ // // by James L. Hammons // +// Currently, we use the ASPI layer for Win32, but this may or may not +// work on NT based Windows. If necessary, we'll put in the required +// NT based code, but for now, it's ASPI or nothing. +// -// OS dependent CDROM stuffola +// *** OS dependent CDROM stuffola *** #include -#include #include "wnaspi32.h" #include "scsidefs.h" -// End OS dependent - +// *** End OS dependent *** #include "log.h" using namespace std; // Local variables -DWORD remain = 0, sector = 0; -BYTE cdBuf[2532 * 10]; +static uint8 maxHostAdapters = 0, numCDDrives = 0, driveNum; +static uint8 haID[8], tID[8]; +static uint8 driveName[8][26]; +static uint8 tracks[100][3]; // One-based index +static uint32 numTracks = 0; +static uint8 sessions[40][5]; // Zero-based index +static uint32 numSessions = 0; +static bool readTOC = false; -// Private function prototypes +static HINSTANCE hASPILib = NULL; // Handle to ASPI for Win32 (WNASPI.DLL) +static uint32 (* ASPI_GetASPI32SupportInfo)(void); // WNASPI.DLL function pointers +static uint32 (* ASPI_SendASPI32Command)(LPSRB); +// Private function prototypes -HINSTANCE WNASPI32_handle = NULL; //Handle to ASPI for Win32 (WNASPI.DLL) -//WNASPI.DLL functions -DWORD (*ASPI_GetASPI32SupportInfo)(VOID); -DWORD (*ASPI_SendASPI32Command)(LPSRB); -//BOOL (*ASPI_GetASPI32Buffer)(PASPI32BUFF); -//BOOL (*ASPI_FreeASPI32Buffer)(PASPI32BUFF); -//BOOL (*ASPI_TranslateASPI32Address)(PDWORD, PDWORD); +static bool InitASPI(void); +static bool SendAsyncASPICmd(uint8, uint8, uint8 *, uint8, uint8 *, uint32, uint8); +/*static*/ bool GetRawTOC(void); -byte DataBuf[2352]; //Buffer for holding data to/from drive -//************************************************************ -//End of globals // -// Load the WNASPI32.DLL and import the required functions, then initialise -// Win ASPI 32. +// Initialize the Win32 ASPI layer // -BOOL InitASPI() +static bool InitASPI(void) { - DWORD dwSupportInfo; - SRB_GetSetTimeouts srbTimeouts; + hASPILib = LoadLibrary("WNASPI32"); + + if (!hASPILib) + { + WriteLog("CDINTF: Could not load WNASPI32.DLL!\n"); + return false; + } - WNASPI32_handle = LoadLibrary("WNASPI32"); //WNASPI32.DLL + ASPI_GetASPI32SupportInfo = (uint32 (*)(void))GetProcAddress(hASPILib, "GetASPI32SupportInfo"); + ASPI_SendASPI32Command = (uint32 (*)(LPSRB))GetProcAddress(hASPILib, "SendASPI32Command"); - if (!WNASPI32_handle) + if (!ASPI_GetASPI32SupportInfo || !ASPI_SendASPI32Command) { - WriteLog("CDINTF: Could not load WNASPI32.DLL\n"); - return FALSE; - }; - - /* - ** Get the ASPI entry points. Note that only two functions are mandatory: - ** GetASPI32SupportInfo and SendASPI32Command. The code will run if the - ** others are not present. - */ - ASPI_GetASPI32SupportInfo = (DWORD (*)(void))GetProcAddress(WNASPI32_handle, "GetASPI32SupportInfo"); - ASPI_SendASPI32Command = (DWORD (*)(LPSRB))GetProcAddress(WNASPI32_handle, "SendASPI32Command"); - //ASPI_GetASPI32Buffer = (BOOL (*)(PASPI32BUFF))GetProcAddress(WNASPI32_handle, "GetASPI32Buffer"); - //ASPI_FreeASPI32Buffer = (BOOL (*)(PASPI32BUFF))GetProcAddress(WNASPI32_handle, "FreeASPI32Buffer"); - //ASPI_TranslateASPI32Address = (BOOL (*)(PDWORD, PDWORD))GetProcAddress(WNASPI32_handle, "TranslateASPI32Address"); - - //Check if the 2 functions were imported. - if(!ASPI_GetASPI32SupportInfo || !ASPI_SendASPI32Command) - { - WriteLog("Could not import GetASPI32SupportInfo & SendASPI32Command functions from WNASPI32.DLL\n"); - return FALSE; - }; - - //Initialise Win ASPI 32 by calling ASPI_GetASPI32SupportInfo(). - dwSupportInfo = ASPI_GetASPI32SupportInfo(); - if (HIBYTE(LOWORD(dwSupportInfo)) != SS_COMP && HIBYTE(LOWORD(dwSupportInfo)) != SS_NO_ADAPTERS) - { - WriteLog("Could not initialise using GetASPI32SupportInfo function or no adapters\n"); - return FALSE; - }; - - /* - ** Set timeouts for ALL devices to 15 seconds. Nothing we deal with should - ** take that long to do ANYTHING. We are just doing inquiries to most - ** devices, and then simple reads to CDs, disks, etc. so 10 seconds (even - ** if they have to spin up) should be plenty. - */ - memset(&srbTimeouts, 0, sizeof(SRB_GetSetTimeouts)); - srbTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS; - srbTimeouts.SRB_HaId = 0xFF; - srbTimeouts.SRB_Flags = SRB_DIR_OUT; - srbTimeouts.SRB_Target = 0xFF; - srbTimeouts.SRB_Lun = 0xFF; - srbTimeouts.SRB_Timeout = 15 * 2; - ASPI_SendASPI32Command(&srbTimeouts); - - return TRUE; -}; - -/* - Sends a SRB (SCSI Request Block) to Win ASPI32 driver for processing and - waits for completion. - - The SRB contains the CDB (Command Descriptor Block) which has the - raw SCSI command/info you want to send to the drive. So effectively - this is actually sending the SCSI command to the drive. - - Note that this uses a Windows event to wait for the drive to reply back - which is efficient. If an event is not available (which should never - happen really) a loop is used to poll for reply back. - - Both methods will wait infinitely - so the drive must reply back otherwise - this software will appear to hang. There seems to be no mechanism for - cancelling the SRB process - the Win ASPI 32 'SC_ABORT_SRB' command doesn't - seem to work. -*/ -BOOL SendASPICMD_and_wait(BYTE HA_ID, BYTE Target_ID, BYTE SRB_flags, DWORD Buffer_len, - PBYTE Buffer, BYTE CDB_len, PBYTE CDB) -{ - DWORD dwASPIStatus; - HANDLE hevent_SRB; //A handle for a new Windows event - SRB_ExecSCSICmd SRB; //The SRB variable with CDB included - BOOL b_retry = TRUE; - - //Clear & setup the SRB for this command.. - memset(&SRB, 0, sizeof(SRB_ExecSCSICmd)); //Set it to zeroes - memcpy(SRB.CDBByte, CDB, CDB_len); //Copy CDB into SRB - - SRB.SRB_Cmd = SC_EXEC_SCSI_CMD; - SRB.SRB_HaId = HA_ID; - SRB.SRB_Target = Target_ID; - //SRB.SRB_Lun = 0; //It's already zero - SRB.SRB_Flags = SRB_flags; - SRB.SRB_BufLen = Buffer_len; - SRB.SRB_BufPointer = Buffer; - SRB.SRB_SenseLen = SENSE_LEN; - SRB.SRB_CDBLen = CDB_len; - - do - { - /* - ** Create an event (if possible) and issue the command. After sending - ** the command, wait for completion. - */ - hevent_SRB = CreateEvent(NULL, TRUE, FALSE, NULL); - if (hevent_SRB) - { - //Windows event method for waiting - efficient. - - SRB.SRB_Flags |= SRB_EVENT_NOTIFY; - SRB.SRB_PostProc = (LPVOID)hevent_SRB; - - //Send the SRB for processing. - dwASPIStatus = ASPI_SendASPI32Command((LPSRB)&SRB); - if (dwASPIStatus == SS_PENDING) - { - //Wait for reply back. - WaitForSingleObject(hevent_SRB, INFINITE); - } - CloseHandle(hevent_SRB); - } - else - { - //Polling method for waiting - not very efficient. - - //Send the SRB for processing. - ASPI_SendASPI32Command((LPSRB)&SRB); - //Wait for reply back. - while(SRB.SRB_Status == SS_PENDING); - }; - - /* - ** Check for errors. We'll retry on unit attention condition. Anything - ** else will generate an error msg. - */ - if (SRB.SRB_Status != SS_COMP) - { - if (b_retry && (SRB.SRB_TargStat != STATUS_CHKCOND - || (SRB.SenseArea[2] & 0x0F) != KEY_UNITATT)) - b_retry = FALSE; - else - { - WriteLog("SCSI command failed.\n"); - return FALSE; - } - } - } - while (b_retry == FALSE); - - return TRUE; -}; - -/* - Lists all available CDROM type drives. This includes: - - CDROM drives - - CD rewriters/Combo - - DVD drives - - DVD rewriters - etc - - It can only list the SCSI IDs not drive letters. Win ASPI 32 does - not provide a mechanism for this. You will have to use windows API - for this. -*/ -VOID ListDevices() -{ - BYTE HaId; - BYTE Target; - BYTE MaxHaId; - BYTE MaxTarget; - BYTE InquiryBuf[36]; - BYTE InquiryCDB[6]; - CHAR szVendor[9]; - CHAR szProduct[17]; - CHAR szRev[5]; - BOOL bSRB_exec; - DWORD dwASPIStatus; - DWORD dwMaxTransferBytes; - SRB_HAInquiry srbHAInquiry; - SRB_GDEVBlock srbGDEVBlock; - DWORD n_CDROM_drives=0; //No of CDROM type drives found. - - //Use support info for host adapter count and loop over all of them. - dwASPIStatus = ASPI_GetASPI32SupportInfo(); - if(HIBYTE(LOWORD(dwASPIStatus)) == SS_COMP) - { - MaxHaId = LOBYTE(LOWORD(dwASPIStatus)); - for(HaId = 0; HaId < MaxHaId; HaId++) - { - /* - ** Do a host adapter inquiry to get max target count. If the - ** target count isn't 8 or 16 then go with a default of 8. - */ - memset(&srbHAInquiry, 0, sizeof(SRB_HAInquiry)); - srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY; - srbHAInquiry.SRB_HaId = HaId; - - ASPI_SendASPI32Command((LPSRB)&srbHAInquiry); - if(srbHAInquiry.SRB_Status != SS_COMP) - { - continue; - }; - - MaxTarget = srbHAInquiry.HA_Unique[3]; - if(MaxTarget != 8 && MaxTarget != 16) - { - MaxTarget = 8; - }; - - /* - ** Loop over all the targets on this host adapter. - */ - for(Target = 0; Target < MaxTarget; Target++ ) - { - /* - ** Issue get device type call to see if there is a device we're - ** interested in at this address. We're interested in CDROMs. - */ - memset(&srbGDEVBlock, 0, sizeof(SRB_GDEVBlock)); - srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; - srbGDEVBlock.SRB_HaId = HaId; - srbGDEVBlock.SRB_Target = Target; - - ASPI_SendASPI32Command((LPSRB)&srbGDEVBlock); - if(srbGDEVBlock.SRB_Status != SS_COMP || - (srbGDEVBlock.SRB_DeviceType != DTYPE_CDROM)) - { - continue; - }; - - /* - ** Determine the max transfer count of this target. It will - ** be the min of the host adapters min count and the size - ** of our global transfer buffer. - */ - dwMaxTransferBytes = (DWORD)&srbHAInquiry.HA_Unique[4]; - - /* - ** Issue an INQUIRY. - */ - memset(InquiryCDB, 0, 6); - InquiryCDB[0] = SCSI_INQUIRY; - InquiryCDB[4] = 36; //Size in bytes of inquiry buffer. - - //Send SCSI device inquiry command and wait for completion. - bSRB_exec = SendASPICMD_and_wait - ( - HaId, - Target, - SRB_DIR_IN, - 36, - InquiryBuf, - 6, - InquiryCDB - ); - - /* - ** Make sure the inquiry worked. If it failed, or if the - ** inquiry data returns a different device type than we got - ** before (guards against certain device drivers and against - ** vendor unique devices). - */ - if(!bSRB_exec || (InquiryBuf[0] != DTYPE_CDROM)) - continue; - - /* - ** Add this target to the screen. - */ - WriteLog("Host adapter ID: %ld\n", HaId); - WriteLog("Target ID : %ld\n", Target); - WriteLog("LUN ID : 0\n"); - WriteLog("Max buffer size: %ld bytes\n", dwMaxTransferBytes); - - memcpy(szVendor, InquiryBuf + 8, 8); - szVendor[8] = '\0'; //Terminate the string - - memcpy(szProduct, InquiryBuf + 16, 16); - szProduct[16] = '\0'; //Terminate the string - - memcpy(szRev, InquiryBuf + 32, 4); - szRev[4] = '\0'; //Terminate the string - - WriteLog("Vendor : %s\n", szVendor); - WriteLog("Product : %s\n", szProduct); - WriteLog("Revision : %s\n\n", szRev); - - n_CDROM_drives++; - } - } - - if (n_CDROM_drives == 0) - WriteLog("No CDROM type drives found.\n"); - } + WriteLog("CDINTF: Could not import functions from WNASPI32.DLL!\n"); + return false; + } + + uint32 supportInfo = ASPI_GetASPI32SupportInfo(); // Initialize ASPI layer + uint8 retCode = (supportInfo >> 8) & 0xFF; + maxHostAdapters = supportInfo & 0xFF; + + if (retCode != SS_COMP && retCode != SS_NO_ADAPTERS) + { + WriteLog("CDINTF: Could not initialise using GetASPI32SupportInfo function!\n"); + return false; + } + + if (retCode == SS_NO_ADAPTERS) + { + WriteLog("CDINTF: ASPI initialized, but no host adapters were found!\n"); + return false; + } + +/* // Set timeouts for ALL devices to 15 seconds. Nothing we deal with should + // take that long to do ANYTHING. We are just doing inquiries to most + // devices, and then simple reads to CDs, disks, etc. so 10 seconds (even + // if they have to spin up) should be plenty. + + SRB_GetSetTimeouts srbTimeouts; +//This doesn't seem to do anything, and isn't even mentioned in Adaptec's ASPI paper... +//(It *is* mentioned elsewhere, in other Adaptec documentation, and it does nothing because it +// errors out!) +//It *does* return code $81 (SS_INVALID_HA) which means it doesn't like $FF for the HAID... +//OK, it works with Adaptec's driver, but not the default MS driver... +//Looks like we really don't need it anyway. +//If we really wanted to, we could do it in CDIntfInit()...! + memset(&srbTimeouts, 0, sizeof(SRB_GetSetTimeouts)); + srbTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS; + srbTimeouts.SRB_Flags = SRB_DIR_OUT; + srbTimeouts.SRB_HaId = 0xFF; + srbTimeouts.SRB_Target = 0xFF; + srbTimeouts.SRB_Lun = 0xFF; + srbTimeouts.SRB_Timeout = 15 * 2; + ASPI_SendASPI32Command(&srbTimeouts); + WriteLog("CDINTF: Set Timeout command returned %02X...\n", srbTimeouts.SRB_Status);//*/ + + WriteLog("CDINTF: Successfully initialized.\n"); + return true; } // -// 1. Sets up the CDB for MMC readcd (CDB12) command. -// 2. Send the request to the drive. -// 3. If success displays the sector data as hex on the screen. +// Sends the passed in Command Description Block to the APSI layer for processing. +// Since this uses the asynchronous EXEC_SCSI_CMD, we also wait for completion by +// using a semaphore. // -BOOL ReadCD(BYTE HA_ID, BYTE Target_ID, long int MMC_LBA_sector) +static bool SendAsyncASPICmd(uint8 hostID, uint8 targID, uint8 * cdb, uint8 CDBLen, + uint8 * buffer, uint32 bufferLen, uint8 SRBFlags) { - BYTE read_CDB12[12]; - long int MMC_LBA_sector2; - - //CDB with values for ReadCD CDB12 command. The values were taken from MMC1 draft paper. - read_CDB12[0] = 0xBE; //Code for ReadCD CDB12 command - read_CDB12[1] = 0; - - read_CDB12[5] = byte(MMC_LBA_sector); //Least sig byte of LBA sector no. to read from CD - MMC_LBA_sector2 = MMC_LBA_sector >> 8; - read_CDB12[4] = byte(MMC_LBA_sector2); //2nd byte of: - MMC_LBA_sector2 = MMC_LBA_sector2 >> 8; - read_CDB12[3] = byte(MMC_LBA_sector2); //3rd byte of: - MMC_LBA_sector2 = MMC_LBA_sector2 >> 8; - read_CDB12[2] = byte(MMC_LBA_sector2); //Most significant byte - - read_CDB12[6] = 0; //No. of sectors to read from CD byte 2 (MSB) - read_CDB12[7] = 0; //No. of sectors to read from CD byte 1 - read_CDB12[8] = 1; //No. of sectors to read from CD byte 0 (LSB) - read_CDB12[9] = 0xF8; //Raw read, 2352 bytes per sector - read_CDB12[10] = 0; //Sub-channel selection bits. - read_CDB12[11] = 0; - - return SendASPICMD_and_wait(HA_ID, Target_ID, SRB_DIR_IN, 2352, DataBuf, 12, read_CDB12); + SRB_ExecSCSICmd SRB; // The SRB variable with CDB included + + memset(&SRB, 0, sizeof(SRB)); + memcpy(SRB.CDBByte, cdb, CDBLen); // Copy CDB into SRB's CDB + + SRB.SRB_Cmd = SC_EXEC_SCSI_CMD; + SRB.SRB_Flags = SRBFlags | SRB_EVENT_NOTIFY; + SRB.SRB_HaId = hostID; + SRB.SRB_Target = targID; + SRB.SRB_BufPointer = buffer; + SRB.SRB_BufLen = bufferLen; + SRB.SRB_CDBLen = CDBLen; + SRB.SRB_SenseLen = SENSE_LEN; + + HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (!hEvent) + { + WriteLog("CDINTF: Couldn't create event!\n"); + return false; + } + + SRB.SRB_PostProc = (void *)hEvent; + ASPI_SendASPI32Command(&SRB); + + if (SRB.SRB_Status == SS_PENDING) + WaitForSingleObject(hEvent, INFINITE); + + CloseHandle(hEvent); + + if (SRB.SRB_Status != SS_COMP) + { + WriteLog("CDINTF: SCSI command %02X failed [Error: %02X].\n", SRB.CDBByte[0], SRB.SRB_Status); + return false; + } + + return true; } // -// Initialize the SDL sound system +// OS specific implementation of OS agnostic functions // -void __CDInit(void) + +bool CDIntfInit(void) { if (!InitASPI()) { - WriteLog("Sound: Failed to init ASPI layer!\n"); - exit(1);//bad! + WriteLog("CDINTF: Failed to init Win32 ASPI layer!\n"); + return false; + } + + SRB_HAInquiry srbHAInquiry; + SRB_GDEVBlock srbGDEVBlock; + uint8 inquiryCDB[6], inquiryBuf[36]; + + for(uint8 HAID=0; HAID=0; i--) + { + if (inquiryBuf[8+i] != ' ') + { + vendorSize = i + 1; + break; + } + } + + for(int i=15; i>=0; i--) + { + if (inquiryBuf[16+i] != ' ') + { + productSize = i + 1; + break; + } + } + + memcpy(driveName[numCDDrives], inquiryBuf + 8, vendorSize); + driveName[numCDDrives][vendorSize] = ' '; + memcpy(driveName[numCDDrives] + vendorSize + 1, inquiryBuf + 16, productSize); + driveName[numCDDrives][vendorSize + productSize + 1] = 0; + + WriteLog("CDINTF: Found CD-ROM device [%s]. HAID:%u, TID:%u LUN:0\n", driveName[numCDDrives], haID[numCDDrives], tID[numCDDrives]); + + numCDDrives++; + } + } + + if (numCDDrives == 0) + { + WriteLog("CDINTF: No CDROM type drives found.\n"); + return false; } + +//Most likely, will need to read a default out of the config file. But for now... !!! FIX !!! + driveNum = 0; // For now, default to first drive found + + return true; } -// -// Close down the SDL sound subsystem -// -void __CDDone(void) +void CDIntfDone(void) { - //Unload ASPI if it has been loaded. - if (WNASPI32_handle) - FreeLibrary(WNASPI32_handle); + if (hASPILib) + FreeLibrary(hASPILib); // Unload ASPI library if it was loaded. } -/*// -// Sound card callback handler -// -void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) +bool CDIntfReadBlock(uint32 sector, uint8 * buffer) +{ + uint8 cdb[12]; + + memset(cdb, 0, sizeof(cdb)); + // 0: command, 2-5: block # (hi->lo) 6-8: number of blocks to read, 9: read type, + // 10: subchannel select + cdb[0] = 0xBE; // Code for ReadCD CDB12 command + cdb[2] = (sector >> 24) & 0xFF; + cdb[3] = (sector >> 16) & 0xFF; + cdb[4] = (sector >> 8) & 0xFF; + cdb[5] = sector & 0xFF; + cdb[8] = 1; // No. of sectors to read from CD (LSB) + cdb[9] = 0xF8; // Raw read, 2352 bytes per sector + cdb[10] = 1; // Selects read RAW 96 bytes/sector sub-channel data (Raw P-W) + + return SendAsyncASPICmd(haID[driveNum], tID[driveNum], cdb, 12, buffer, 2352+96, SRB_DIR_IN); +} + +uint32 CDIntfGetNumSessions(void) { - if (remain > 0) +// WriteLog("CDINTF: GetNumSessions unimplemented!\n"); + // Still need relevant code here... !!! FIX !!! [DONE] + if (!readTOC) + GetRawTOC(); + + return numSessions - 1; +} + +void CDIntfSelectDrive(uint32 driveNum) +{ + if (driveNum < numCDDrives) + driveNum = driveNum; +} + +uint32 CDIntfGetCurrentDrive(void) +{ + return driveNum; +} + +const uint8 * CDIntfGetDriveName(uint32 driveNum) +{ + if (driveNum > numCDDrives) + return NULL; + + return driveName[driveNum]; +} + +//This stuff could probably be OK in the unified cdintf.cpp file... +uint8 CDIntfGetSessionInfo(uint32 session, uint32 offset) +{ +// Need better error handling than this... !!! FIX !!! + if (!readTOC) + if (!GetRawTOC()) + return 0xFF; + + if (session >= numSessions || offset > 4) + return 0xFF; // Bad index passed in... + + return sessions[session][offset]; +} + +uint8 CDIntfGetTrackInfo(uint32 track, uint32 offset) +{ +// Need better error handling than this... !!! FIX !!! + if (!readTOC) + if (!GetRawTOC()) + return 0xFF; + + if (track > numTracks || offset > 2) + return 0xFF; // Bad index passed in... + + return tracks[track][offset]; +} + +//OK, now the rest is OK, but this is still locking up like a MF! +// Testing, testing... +//Still don't know why this is locking up! Especially as the following function works! Aarrrgggghhhhh! +//It was the dataLen. For some reason, it needs at *least* 11 more bytes (could be less!) +/*static*/ bool GetRawTOC(void) +{ + uint8 cmd[10]; + uint8 reqData[4]; + + // Read disk TOC length + memset(cmd, 0, 10); + cmd[0] = SCSI_READ_TOC; + cmd[2] = 2; // Get session info also + cmd[6] = 1; // Session # to start reading + cmd[8] = 4; // Buffer length + + if (!SendAsyncASPICmd(haID[driveNum], tID[driveNum], cmd, 10, reqData, 4, SRB_DIR_IN)) { - memcpy(buffer, DataBuf + 2352 - remain, remain); - length -= remain; - buffer += remain; - remain = 0; + WriteLog("TOC: Cannot read disk TOC length.\n"); + return false; } - while (length > 0) + // Header is total TOC space needed + header (0-1), min session (2), max session (3) +// uint32 dataLen = ((reqData[0] << 8) | reqData[1]); + uint32 dataLen = ((reqData[0] << 8) | reqData[1]) + 11; // Why the extra??? + + WriteLog("TOC: Raw TOC data len: %d\n", dataLen); + + uint8 * data = new uint8[dataLen]; + + // Read disk TOC + cmd[7] = dataLen >> 8; + cmd[8] = dataLen; + + if (!SendAsyncASPICmd(haID[driveNum], tID[driveNum], cmd, 10, data, dataLen, SRB_DIR_IN)) { - ReadCD(0, 1, sector++); - memcpy(buffer, DataBuf, (length >= 2352 ? 2352 : length)); - length -= 2352; - buffer += 2352; + delete[] data; + WriteLog("TOC: Cannot read disk TOC.\n"); + return false; } - if (length < 0) - remain = -length; -}*/ + int numEntries = (((data[0] << 8) | data[1]) - 2) / 11; + uint8 * p = data + 4; + + numSessions = data[3], numTracks = 0; + // Important entries are 0, 3, 8, 9, 10 (session #, track #, M, S, F) +// WriteLog("TOC: [Sess] [adrCtl] [?] [point] [?] [?] [?] [?] [pmin] [psec] [pframe]\n"); + uint32 firstTrackOffset = 0; + for(int i=0; i 0 && p[3] < 99) + WriteLog(" <-- Track #%u", p[3]); + + WriteLog("\n");//*/ + + // We do session # - 1 to make it zero-based, since this is what the Jaguar + // CD BIOS expects. We leave the tracks one-based. + + uint32 s = p[0] - 1, t = p[3]; + + if (t < 100) + { + if (t == 1) + firstTrackOffset = (((p[8] * 60) + p[9]) * 75) + p[10]; + + tracks[t][0] = p[8], tracks[t][1] = p[9], tracks[t][2] = p[10]; + + // For some reason, the TOC returned from the "session TOC" command + // causes all tracks to have a 150 block (from what I've seen) offset + // from what's reported. Apparently it's not possible to read those + // first 150 blocks using the current incarnation of CDIntf_ReadBlock. + // So we subtract the offset out here... + + uint32 curTrack = (((tracks[t][0] * 60) + tracks[t][1]) * 75) + tracks[t][2]; + curTrack -= firstTrackOffset; + tracks[t][2] = curTrack % 75; + curTrack /= 75; + tracks[t][1] = curTrack % 60; + tracks[t][0] = curTrack / 60; + + if (t > numTracks) + numTracks = t; + } + else if (t == 0xA0) + sessions[s][0] = p[8]; + else if (t == 0xA1) + sessions[s][1] = p[8]; + else if (t == 0xA2) + sessions[s][2] = p[8], sessions[s][3] = p[9], sessions[s][4] = p[10]; + } + +WriteLog("CDINTF: Disc summary\n # of sessions: %u, # of tracks: %u\n", numSessions, numTracks); +WriteLog(" Session info:\n"); +for(uint32 i=0; i