diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-24 03:15:42 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-24 03:15:42 +0000 |
| commit | 5408345d8b1cde19a19ddf324d3439ead6e80709 (patch) | |
| tree | fd7934308384396b4ad92b547e8804a696c480e8 /macosx/plugins/CDDeviceInterface/src/PlugCD.c | |
| parent | f2f1033882e0643f05f3027f2c812f425f67a879 (diff) | |
| download | pcsxr-5408345d8b1cde19a19ddf324d3439ead6e80709.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@32699 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'macosx/plugins/CDDeviceInterface/src/PlugCD.c')
| -rw-r--r-- | macosx/plugins/CDDeviceInterface/src/PlugCD.c | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/macosx/plugins/CDDeviceInterface/src/PlugCD.c b/macosx/plugins/CDDeviceInterface/src/PlugCD.c new file mode 100644 index 00000000..549e137c --- /dev/null +++ b/macosx/plugins/CDDeviceInterface/src/PlugCD.c @@ -0,0 +1,889 @@ +/*************************************************************************** + PlugCD.c + CDDeviceInterface + + Created by Gil Pedersen on Fri July 18 2003. + Copyright (c) 2003,2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <paths.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <pthread.h> +#include <mach/mach_port.h> + +#include <IOKit/IOKitLib.h> +#include <IOKit/IOBSD.h> +#include <IOKit/storage/IOCDMedia.h> +#include <IOKit/storage/IOMedia.h> +#include <IOKit/storage/IOCDTypes.h> +#include <IOKit/storage/IOCDMediaBSDClient.h> +#include <IOKit/scsi-commands/SCSITaskLib.h> +#include <CoreFoundation/CoreFoundation.h> + +//#include "plugins.h" +#include "PlugCD.h" + +//#define USE_DEVICE_INTERFACE + +long CDRclose(void); + +///////////////////////////////////////////////////////// +typedef void* HWND; +#include "PSEmu_Plugin_Defs.h" + +const char *LibName = "CD-ROM Device Interface"; +const int version = 0; +const int revision = 1; +const int build = 0; + +const char *PSEgetLibName(void) { + return LibName; +} + +unsigned long PSEgetLibType(void) { + return PSE_LT_CDR; +} + +unsigned long PSEgetLibVersion(void) { + return version << 16 | revision << 8 | build; +} +///////////////////////////////////////////////////////// + +//#define SysPrintf printf +#define SysPrintf(X) + +#define UseMultiThreaded 1 +#define NoIdleSleep 1 + +struct CdrStat { + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; +}; + +MMCDeviceInterface **cdInterface; +pthread_t readThread; +pthread_cond_t readCond; +pthread_mutex_t readMutex; +char deviceFilePath[ 256 ]; + +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator, mach_port_t *masterPort ) +{ + kern_return_t kernResult; + CFMutableDictionaryRef classesToMatch; + + kernResult = IOMasterPort( bootstrap_port, masterPort ); + if ( kernResult != KERN_SUCCESS ) + { + printf( "IOMasterPort returned %d\n", kernResult ); + return kernResult; + } + // CD media are instances of class kIOCDMediaClass. + classesToMatch = IOServiceMatching( kIOCDMediaClass ); + if ( classesToMatch == NULL ) + printf( "IOServiceMatching returned a NULL dictionary.\n" ); + else + { + // Each IOMedia object has a property with key kIOMediaEjectable + // which is true if the media is indeed ejectable. So add property + // to CFDictionary for matching. + CFDictionarySetValue( classesToMatch, + CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); + } + kernResult = IOServiceGetMatchingServices( *masterPort, + classesToMatch, mediaIterator ); + if ( (kernResult != KERN_SUCCESS) || (*mediaIterator == NULL) ) + printf( "No ejectable CD media found.\n kernResult = %d\n", + kernResult ); + return kernResult; +} + +kern_return_t GetDeviceFilePath( io_service_t media, + char *deviceFilePath, CFIndex maxPathSize ) +{ + kern_return_t kernResult = KERN_FAILURE; + CFTypeRef deviceFilePathAsCFString; + + deviceFilePathAsCFString = IORegistryEntryCreateCFProperty( + media, CFSTR( kIOBSDNameKey ), + kCFAllocatorDefault, 0 ); + *deviceFilePath = '\0'; + if ( deviceFilePathAsCFString ) + { + size_t devPathLength = strlen( _PATH_DEV )+0;//+1; + + strcpy( deviceFilePath, _PATH_DEV ); + // Add "r" before the BSD node name from the I/O Registry + // to specify the raw disk node. The raw disk node receives + // I/O requests directly and does not go through the + // buffer cache. + // strcat( deviceFilePath, "r"); // apparently som cd-rom drives don't like this + + if ( CFStringGetCString( deviceFilePathAsCFString, + deviceFilePath + devPathLength, + maxPathSize - devPathLength, + kCFStringEncodingASCII ) ) + { + printf( "BSD path: %s\n", deviceFilePath ); + kernResult = KERN_SUCCESS; + } + CFRelease( deviceFilePathAsCFString ); + } + + return kernResult; +} + +MMCDeviceInterface ** GetMMCInterfaceForDevice(io_service_t service) +{ + SInt32 score; + HRESULT herr; + kern_return_t err; + IOCFPlugInInterface **plugInInterface = NULL; + MMCDeviceInterface **mmcInterface = NULL; + + // Create the IOCFPlugIn interface so we can query it. + err = IOCreatePlugInInterfaceForService ( service, + kIOMMCDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, + &score ); + + if ( err != noErr ) + { + printf("IOCreatePlugInInterfaceForService returned %d\n", err); + return NULL; + } + + // Query the interface for the MMCDeviceInterface. + herr = ( *plugInInterface )->QueryInterface ( plugInInterface, + CFUUIDGetUUIDBytes ( kIOMMCDeviceInterfaceID ), + ( LPVOID ) &mmcInterface ); + if ( herr != S_OK ) + { + printf("QueryInterface returned %ld\n", herr); + return NULL; + } + +// ( *mmcInterface )->Release ( mmcInterface ); +// IODestroyPlugInInterface ( plugInInterface ); + + return mmcInterface; +} + +int GetCDROMServices() +{ + mach_port_t masterPort; + CFMutableDictionaryRef matchingDict; + CFMutableDictionaryRef subDict; + io_service_t nextDevice; + io_iterator_t iterator; + kern_return_t kr; + int retVal = -1; + + // first create a master_port for my task + kr = IOMasterPort(MACH_PORT_NULL, &masterPort); + if (kr || !masterPort) + { + printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr); + return -1; + } + + // Create the dictionaries + matchingDict = CFDictionaryCreateMutable ( kCFAllocatorDefault, 0, NULL, NULL ); + subDict = CFDictionaryCreateMutable ( kCFAllocatorDefault, 0, NULL, NULL ); + + // Create a dictionary with the "SCSITaskDeviceCategory" key = "SCSITaskAuthoringDevice" + // TODO: examine if this also work on non-authoring capable devices + CFDictionarySetValue ( subDict, + CFSTR ( kIOPropertySCSITaskDeviceCategory ), + CFSTR ( kIOPropertySCSITaskAuthoringDevice ) ); + + // Add the dictionary to the main dictionary with the key "IOPropertyMatch" to + // narrow the search to the above dictionary. + CFDictionarySetValue ( matchingDict, + CFSTR ( kIOPropertyMatchKey ), + subDict ); + + + kr = IOServiceGetMatchingServices( masterPort, + matchingDict, &iterator ); + if ( (kr != KERN_SUCCESS) || (iterator == NULL) ) { + printf( "No CDROM drives found.\n kernResult = %d\n", kr ); + goto error; + } + + // Find best cdrom drive - i.e. the first :-) + while(nextDevice = IOIteratorNext( iterator )) { + cdInterface = GetMMCInterfaceForDevice(nextDevice); + kr = IOObjectRelease(nextDevice); + break; // hack + } + IOObjectRelease( iterator ); + + retVal = 0; +error: + // Now done with the master_port + if (masterPort) + mach_port_deallocate(mach_task_self(), masterPort); + + return retVal; +} + +/* determine if the tray is open for our cd-drive */ +int TrayIsOpen() +{ +#ifdef USE_DEVICE_INTERFACE + if (cdInterface) { + if ((*cdInterface)->GetTrayState) { + IOReturn res; + char state; + + res = (*cdInterface)->GetTrayState(cdInterface, &state); + if (kIOReturnSuccess == res) { + if (kMMCDeviceTrayOpen == state) + return true; + } + } + } +#endif + return true; +} + +/* opens tray if no media is in the device */ +void TrayOpen() +{ + if (TrayIsOpen()) + return; + + if (cdInterface) { + if ((*cdInterface)->SetTrayState) { + (*cdInterface)->SetTrayState(cdInterface, kMMCDeviceTrayOpen); + } + } +} + +long openDisc() +{ + mach_port_t masterPort = NULL; + kern_return_t kernResult; + io_iterator_t mediaIterator; + io_service_t media; + CFTypeRef toc_cf; + //dk_cd_read_disc_info_t cd_read_disc_info; + //dk_cd_read_track_info_t cd_read_track_info; + //CDDiscInfo di; CDTrackInfo ti; + u_int16_t speed; + int i; + + CD.cd = 0; + CD.status = 0x10; + + // Find 1st CD + kernResult = FindEjectableCDMedia( &mediaIterator, &masterPort ); + if ( kernResult != KERN_SUCCESS ) + return -1; + + media = IOIteratorNext( mediaIterator ); + if (NULL == media) + return -1; + + // Release the iterator. + IOObjectRelease( mediaIterator ); + + // Get The device path + kernResult = GetDeviceFilePath( media, deviceFilePath, + sizeof( deviceFilePath ) ); + if ( kernResult != KERN_SUCCESS ) + return -1; + + toc_cf = IORegistryEntryCreateCFProperty(media,CFSTR(kIOCDMediaTOCKey),kCFAllocatorDefault,0); + if(toc_cf != nil) + { + CDTOC *toc = (CDTOC *)CFDataGetBytePtr(toc_cf); + int ndesc; + + ndesc = CDTOCGetDescriptorCount(toc); + if (CD.tl) free(CD.tl); + CD.tl = calloc(ndesc, sizeof(Track)); + if (NULL == CD.tl) + return -1; + + CD.numtracks = 0; + for (i=0; i<ndesc; i++) + { + CDTOCDescriptor *desc = &toc->descriptors[i]; + + if(desc->point < 100) + { + CD.tl[CD.numtracks].type = ((desc->control & 0x0f) != 0) ? Mode2 : Audio; // TODO: set correct type + CD.tl[CD.numtracks].num = desc->point; + CD.tl[CD.numtracks].start[2] = desc->p.frame; + CD.tl[CD.numtracks].start[1] = desc->p.second; + CD.tl[CD.numtracks].start[0] = desc->p.minute; + + if (CD.numtracks) { + CD.tl[CD.numtracks-1].end[2] = desc->p.frame; + CD.tl[CD.numtracks-1].end[1] = desc->p.second; + CD.tl[CD.numtracks-1].end[0] = desc->p.minute; + } + //normalizeTime(CD.tl[0].start); + //normalizeTime(CD.tl[0].end); + CD.numtracks++; + } + } + CDMSF end = CDConvertTrackNumberToMSF(0xa2, toc); + CD.tl[CD.numtracks-1].end[2] = end.frame; + CD.tl[CD.numtracks-1].end[1] = end.second; + CD.tl[CD.numtracks-1].end[0] = end.minute; + + CFRelease(toc_cf); + } else { + printf("failed to read cdrom toc information\n"); + IOObjectRelease( mediaIterator ); + return -1; + } + + IOObjectRelease( media ); + + // Free master port if we created one. + if (masterPort) + mach_port_deallocate(mach_task_self(), masterPort); + + // Now open it + CD.cd = open(deviceFilePath, O_RDONLY, 0); + if (CD.cd <= 0) { + perror("failed to open cd: "); + CD.cd = 0; + return -1; + } + + // get number of tracks +/* memset(&cd_read_disc_info, 0, sizeof(dk_cd_read_disc_info_t)); + cd_read_disc_info.bufferLength = sizeof(CDDiscInfo); + cd_read_disc_info.buffer = &di; + if (ioctl(CD.cd, DKIOCCDREADDISCINFO, &cd_read_disc_info) < 0) { + perror("error reading cd info: "); + CD.numtracks = 1; + } + else { + CD.numtracks = di.lastTrackNumberInLastSessionLSB-di.firstTrackNumberInLastSessionLSB+1; + } + + CD.tl = calloc(CD.numtracks, sizeof(Track)); + for (i=0; i<CD.numtracks; i++) + { + int blocks; + memset(&cd_read_track_info, 0, sizeof(dk_cd_read_track_info_t)); + cd_read_track_info.address = di.firstTrackNumberInLastSessionLSB+i; + cd_read_track_info.addressType = kCDTrackInfoAddressTypeTrackNumber; + cd_read_track_info.bufferLength = sizeof(CDTrackInfo); + cd_read_track_info.buffer = &ti; + if (ioctl(CD.cd, DKIOCCDREADTRACKINFO, &cd_read_track_info) < 0) { + perror("error reading track info"); + close(CD.cd); CD.cd = 0; + return -1; + } + + //printf("Track %i: %i - %i\n", di.firstTrackNumberInLastSessionLSB+i, + // ti.trackStartAddress, ti.trackSize); + + CD.tl[i].type = ti.trackMode ? Mode2 : Audio; // TODO: set correct type + CD.tl[i].num = ti.trackNumberLSB; + blocks = ti.trackStartAddress; + CD.tl[i].start[2] = blocks % 75; + CD.tl[i].start[1] = ((blocks - CD.tl[i].end[2]) / 75) % 60; + CD.tl[i].start[0] = (((blocks - CD.tl[i].end[2]) / 75) - CD.tl[i].end[1]) / 60; + blocks += ti.trackSize; + CD.tl[i].end[2] = blocks % 75; + CD.tl[i].end[1] = ((blocks - CD.tl[i].end[2]) / 75) % 60; + CD.tl[i].end[0] = (((blocks - CD.tl[i].end[2]) / 75) - CD.tl[i].end[1]) / 60; + + normalizeTime(CD.tl[i].start); + normalizeTime(CD.tl[i].end); + }*/ + + speed = kCDSpeedMin*4; // 4x + if (ioctl(CD.cd, DKIOCCDSETSPEED, &speed) < 0) + perror("couldn't set cd speed"); + + CD.sectorType = kCDSectorTypeMode2Form1; + CD.bufferSize = 0; + CD.bufferPos = 0x7FFFFFFF; + CD.status = 0x00; + +// fcntl(CD.cd, F_RDAHEAD, 1); +// fcntl(CD.cd, F_NOCACHE, 0); + fcntl(CD.cd, F_RDAHEAD, 0); + fcntl(CD.cd, F_NOCACHE, 1); + + return 0; +} + +// gets track +long getTN(unsigned char* buffer) +{ + int numtracks = getNumTracks(); + + if (-1 == numtracks) + { + buffer[0]=buffer[1]=1; + return -1; + } + + buffer[0]=CD.tl[0].num; + buffer[1]=numtracks; + return 0; +} + + // if track==0 -> return total length of cd + // otherwise return start in bcd time format +long getTD(int track, unsigned char* buffer) +{ + // lasttrack just keeps track of which track TD was requested last (go fig) + + if (track > getNumTracks()) + { +// printf("getTD bad %2d\n", track); + return -1; + } + + if (track == 0) + { + buffer[0] = CD.tl[CD.numtracks-1].end[0]; + buffer[1] = CD.tl[CD.numtracks-1].end[1]; + buffer[2] = CD.tl[CD.numtracks-1].end[2]; + } + else + { + buffer[0] = CD.tl[track-1].start[0]; + buffer[1] = CD.tl[track-1].start[1]; + buffer[2] = CD.tl[track-1].start[2]; + } +// printf("getTD %2d %02d:%02d:%02d\n", track, (int)buffer[0], +// (int)buffer[1], (int)buffer[2]); + + // bcd encode it + buffer[0] = intToBCD(buffer[0]); + buffer[1] = intToBCD(buffer[1]); + buffer[2] = intToBCD(buffer[2]); +// SysPrintf("end getTD()\r\n"); + return 0; +} + +// return the sector address - the buffer address + 12 bytes for subheader offset. +unsigned char* getSector(int subchannel) +{ + SysPrintf("getSector()\n"); + + if (readThread) { + int err; + // wait until we can obtain a lock */ + err = pthread_mutex_lock(&readMutex); + if (err != 0) { + printf("failed to lock mutex, error = %i\n", err); + } else { + err = pthread_mutex_unlock(&readMutex); + if (err != 0) { + printf("failed to unlock mutex, error = %i\n", err); + } + } + } + + if (CD.sector == -1) + return NULL; + else { + return CD.buffer /*+ (CD.sector - CD.bufferPos)*/ + ((subchannel) ? 0 : 12); + } +} + +// returns the number of tracks +char getNumTracks() +{ +// SysPrintf("start getNumTracks()\r\n"); + // if there's no open cd, return -1 + if (CD.cd == 0) { + return -1; + } + +// printf("numtracks %d\n",CD.numtracks); +// SysPrintf("end getNumTracks()\r\n"); + return CD.numtracks; +} + +// read the sector pointed to by pos +int readSector(off_t pos, unsigned char *buffer) +{ + int len; + + SysPrintf("start readit()\n"); + + if (0 == CD.cd) + return 0; + + // go to the sector + pos = lseek(CD.cd, pos, SEEK_SET); + if (pos < 0) + goto error; + + // and read it into the buffer + len = read(CD.cd, buffer, 2352); + if (len < 2352) + goto error; + + SysPrintf("end readit()\n"); + return 2352; + +error: + perror("CD read error"); + return 0; +} + +void seekSector(const unsigned char m, const unsigned char s, const unsigned char f) +{ + int err; + SysPrintf("start seekSector()\n"); + + if (0 == CD.cd) + return; + + if (readThread) { + // wait until we're done reading + err = pthread_mutex_lock(&readMutex); + if (err != 0) { + printf("failed to lock mutex, error = %i\n", err); + } else { + // calc byte to search for + CD.sector = (( (m * 60) + (s - 2)) * 75 + f) * 2352; + + // unlock again, since the mutex won't be set until + // we signal a cond later in this function + err = pthread_mutex_unlock(&readMutex); + if (err != 0) { + printf("failed to unlock mutex, error = %i\n", err); + } + } + } else { + // calc byte to search for + CD.sector = (( (m * 60) + (s - 2)) * 75 + f) * 2352; + } +// printf("seek %d %02d:%02d:%02d",CD.sector, (int)m, (int)s, (int)f); + + // is it cached? +#if 0 + if ((CD.sector >= CD.bufferPos) && + (CD.sector < (CD.bufferPos + CD.bufferSize)) ) { +// printf(" cached %d %d\n",CD.sector - CD.bufferPos,BUFFER_SIZE); +// SysPrintf("end seekSector()\r\n"); + return; + } + // not cached - read a few blocks into the cache + else +#endif + { + if (readThread) { + SysPrintf("end seekSector()\n"); + + // signal that a new sector is ready to be read + if (pthread_cond_broadcast(&readCond) == 0) + return; + + printf("failed to signal 'readCond'\n"); + } + + CD.bufferSize = readSector(CD.sector, CD.buffer); + if (CD.bufferSize==0) CD.sector = -1; + else CD.bufferPos = CD.sector; + } + SysPrintf("end seekSector()\n"); +} + +/* handles reading from the cd */ +void *read_thread(void *arg) +{ + struct timespec dT = { 20, 0 }; // 20 s + //struct timespec dT = { 0, 400*1000*1000 }; // 400 ms + int err; + + pthread_mutex_lock(&readMutex); + //pthread_cleanup_push(pthread_exit, 0); + + for (;;) { + // wait until we're signalled + if (NoIdleSleep) { + err = pthread_cond_timedwait_relative_np(&readCond, &readMutex, &dT); + pthread_testcancel(); + } else { + err = pthread_cond_wait(&readCond, &readMutex); + } + if (err == EINVAL) { + printf("failed cond wait for 'readCond', error = %i\n", err); + return (void *)-1; + } + + CD.bufferSize = readSector(CD.sector, CD.buffer); + if (CD.bufferSize==0) CD.sector = -1; + else CD.bufferPos = CD.sector; + } + //pthread_cleanup_pop(1); + + return 0; +} + +long CDRopen(void) +{ + SysPrintf("CDR_open()\n"); + if (UseMultiThreaded && !readThread) { + int err; + + err = pthread_cond_init(&readCond, NULL); + if (err!=0) { + printf("failed to create conditional, error=%i\n" + "going to single thread mode\n", err); + } else { + err = pthread_mutex_init(&readMutex, NULL); + if (err!=0) { + printf("failed to create mutex, error=%i\n" + "going to single thread mode\n", err); + } else { + struct sched_param params; + int policy; + + err = pthread_create(&readThread, NULL, read_thread, NULL); + if (err!=0) { + printf("failed to create read thread, error=%i\n" + "going to single thread mode\n", err); + } else { + // set the thread to maximum priority + pthread_getschedparam(readThread, &policy, ¶ms); + params.sched_priority = sched_get_priority_max(policy); + pthread_setschedparam(readThread, policy, ¶ms); + } + } + } + } + + if (openDisc() < 0) { + TrayOpen(); + return 0; + } + + seekSector(0,2,0); + + SysPrintf("end CDR_open()\n"); + return 0; +} + +long CDRinit(void) { + +#ifdef USE_DEVICE_INTERFACE + return GetCDROMServices(); +#endif + + return 0; +} + +long CDRshutdown(void) { + // do cleanup + CDRclose(); + + return 0; +} + +long CDRclose(void) { + SysPrintf("start CDR_close()\n"); + + if (!CD.cd) + return 0; + + if (readThread) { + int termVal = 0; + // make sure we're done reading + pthread_mutex_lock(&readMutex); + pthread_mutex_unlock(&readMutex); + + // kill read thread + pthread_cancel(readThread); + //pthread_kill(readThread, SIGTERM); + pthread_cond_broadcast(&readCond); + pthread_join(readThread, (void **)&termVal); + + // remove fluff + pthread_mutex_destroy(&readMutex); + pthread_cond_destroy(&readCond); + + readThread = 0; + } + + close(CD.cd); + CD.cd = 0; + + SysPrintf("end CDR_close()\n"); + return 0; +} + +long CDRgetTN(unsigned char *buffer) { + //printf("start CDRgetTN()\n"); + return getTN(buffer); +} + +long CDRgetTD(unsigned char track, unsigned char *buffer) { + unsigned char temp[3]; + int result = getTD((int)track, temp); + + // printf("start CDRgetTD()\n"); + + if (result == -1) return -1; + + buffer[1] = temp[1]; + buffer[2] = temp[0]; + + return 0; +} + +/* called when the psx requests a read */ +long CDRreadTrack(unsigned char *time) { +// SysPrintf("start CDR_readTrack()\r\n"); + //printf("readTrack at %02d:%02d:%02d\n", BCDToInt(time[0]), BCDToInt(time[1]), BCDToInt(time[2])); + + if (CD.cd != 0) + seekSector(BCDToInt(time[0]), BCDToInt(time[1]), BCDToInt(time[2])); + +// SysPrintf("end CDR_readTrack()\r\n"); + return PSE_CDR_ERR_SUCCESS; +} + +/* called after the read should be finished, and the data is needed */ +unsigned char *CDRgetBuffer(void) { + //printf("start CDR_getBuffer()\n"); +// SysPrintf("start CDR_getBuffer()\r\n"); + if (CD.cd == 0) + return NULL; + + return getSector(0); +} + +unsigned char *CDRgetBufferSub(void) { + //printf("start CDR_getBuffer()\n"); +// SysPrintf("start CDR_getBuffer()\r\n"); + return getSector(1); +} + +/* from PSX manual p. 83 */ +#define CDR_STATUS_UNKNOWN 0x00 +#define CDR_STATUS_ERROR 0x02 /* command error detected */ +#define CDR_STATUS_STANDBY 0x04 /* spindle motor rotating */ +#define CDR_STATUS_SEEK_ERROR 0x08 /* seek error detected */ +#define CDR_STATUS_SHELL_OPEN 0x10 /* once shell open */ +#define CDR_STATUS_READING 0x20 /* reading data sectors */ +#define CDR_STATUS_SEEKING 0x40 +#define CDR_STATUS_PLAYING 0x80 /* playing CD-DA */ + +// reads cdr status - from old plugin +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: (only shell open supported) +// 0x00 - unknown +// 0x01 - error +// 0x04 - seek error -> no disk??? +// 0x10 - shell open -> tray open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + +long CDRgetStatus(struct CdrStat *stat) +{ + if (CD.cd == 0) { + // no cd - check for disc + if (openDisc() < 0) { + if (TrayIsOpen()) { + stat->Type = 0xff;//0x00; + stat->Status |= CDR_STATUS_SHELL_OPEN; + } else { + TrayOpen(); + stat->Type = 0xff; // indicates no cd + stat->Status = CDR_STATUS_UNKNOWN; + } + stat->Time[0] = + stat->Time[1] = + stat->Time[2] = 0; + return 0; + } + } + + if (CD.tl[0].type == Mode1 || CD.tl[0].type == Mode2) { + stat->Type = 0x01; + stat->Status = CDR_STATUS_UNKNOWN; + } else if (CD.tl[0].type == Audio) { + stat->Type = 0x02; + stat->Status = CDR_STATUS_UNKNOWN; // FIXME + } else { + stat->Type = 0x00; + stat->Status = CDR_STATUS_UNKNOWN; // FIXME + } + + stat->Time[0] = + stat->Time[1] = + stat->Time[2] = 0; // FIXME + + return 0; +} + +char *CDRgetDriveLetter(void) { + //printf("start CDR_getBuffer()\n"); +// SysPrintf("start CDR_getBuffer()\r\n"); + return deviceFilePath; +} + +#if 0 +AudioFilePlayID cdFilePlayID; +long CDRplay(unsigned char *sector) +{ + // TODO: find the correct track... + + NewAudioFilePlayID(&fsref, &cdFilePlayID); + + return 0; +} + +long CDRstop(void) +{ + + return 0; +} +#endif +/* +long (CALLBACK* CDRconfigure)(void); +long (CALLBACK* CDRtest)(void); +void (CALLBACK* CDRabout)(void); +*/ + +#ifdef TEST +int main (int argc, int *argv) +{ + CDRopen(); + CDRclose(); + return 0; +} +#endif |
