From ef79bbde537d6b9c745a7d86cb9df1d04c35590d Mon Sep 17 00:00:00 2001 From: PCSX* teams Date: Tue, 16 Nov 2010 14:15:22 +0200 Subject: pcsxr-1.9.92 --- plugins/dfcdrom/cdr.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 515 insertions(+) create mode 100644 plugins/dfcdrom/cdr.c (limited to 'plugins/dfcdrom/cdr.c') diff --git a/plugins/dfcdrom/cdr.c b/plugins/dfcdrom/cdr.c new file mode 100644 index 0000000..f011684 --- /dev/null +++ b/plugins/dfcdrom/cdr.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2010, Wei Mingzhi . + * All Rights Reserved. + * + * Based on: Cdrom for Psemu Pro like Emulators + * By: linuzappz + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "cdr.h" + +#ifndef USE_NULL +static char *LibName = N_("CD-ROM Drive Reader"); +#else +static char *LibName = N_("CDR NULL Plugin"); +#endif + +int initial_time = 0; + +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +CacheData *cdcache; +unsigned char *cdbuffer; +int cacheaddr; + +crdata cr; + +unsigned char lastTime[3]; +pthread_t thread; +int subqread; +volatile int stopth, found, locked, playing; + +long (*ReadTrackT[])() = { + ReadNormal, + ReadThreaded, +}; + +unsigned char* (*GetBufferT[])() = { + GetBNormal, + GetBThreaded, +}; + +long (*fReadTrack)(); +unsigned char* (*fGetBuffer)(); + +void *CdrThread(void *arg); + +long CDRinit(void) { + thread = (pthread_t)-1; + return 0; +} + +long CDRshutdown(void) { + return 0; +} + +long CDRopen(void) { + LoadConf(); + +#ifndef _MACOSX + if (IsCdHandleOpen()) + return 0; // it's already open +#endif + + if (OpenCdHandle(CdromDev) == -1) { // if we can't open the cdrom we'll works as a null plugin + fprintf(stderr, "CDR: Could not open %s\n", CdromDev); + } + + fReadTrack = ReadTrackT[ReadMode]; + fGetBuffer = GetBufferT[ReadMode]; + + if (ReadMode == THREADED) { + cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData)); + if (cdcache == NULL) return -1; + memset(cdcache, 0, CacheSize * sizeof(CacheData)); + + found = 0; + } else { + cdbuffer = cr.buf + 12; /* skip sync data */ + } + + if (ReadMode == THREADED) { + pthread_attr_t attr; + + pthread_mutex_init(&mut, NULL); + pthread_cond_init(&cond, NULL); + locked = 0; + + pthread_attr_init(&attr); + pthread_create(&thread, &attr, CdrThread, NULL); + + cacheaddr = -1; + } else thread = (pthread_t)-1; + + playing = 0; + stopth = 0; + initial_time = 0; + + return 0; +} + +long CDRclose(void) { + if (!IsCdHandleOpen()) return 0; + + if (playing) CDRstop(); + + CloseCdHandle(); + + if (thread != (pthread_t)-1) { + if (locked == 0) { + stopth = 1; + while (locked == 0) usleep(5000); + } + + stopth = 2; + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + pthread_join(thread, NULL); + pthread_mutex_destroy(&mut); + pthread_cond_destroy(&cond); + } + + if (ReadMode == THREADED) { + free(cdcache); + } + + return 0; +} + +// return Starting and Ending Track +// buffer: +// byte 0 - start track +// byte 1 - end track +long CDRgetTN(unsigned char *buffer) { + long ret; + + if (!IsCdHandleOpen()) { + buffer[0] = 1; + buffer[1] = 1; + return 0; + } + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTN(buffer); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +long CDRgetTD(unsigned char track, unsigned char *buffer) { + long ret; + + if (!IsCdHandleOpen()) { + memset(buffer + 1, 0, 3); + return 0; + } + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTD(track, buffer); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +// normal reading +long ReadNormal() { + if (ReadSector(&cr) == -1) + return -1; + + return 0; +} + +unsigned char* GetBNormal() { + return cdbuffer; +} + +// threaded reading (with cache) +long ReadThreaded() { + int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + int i; + + if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && cacheaddr != -1) { + i = addr - cacheaddr; + PRINTF("found %d\n", (addr - cacheaddr)); + cdbuffer = cdcache[i].cr.buf + 12; + while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 || + btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 || + btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) { + if (locked == 1) { + if (cdcache[i].ret == 0) break; + return -1; + } + usleep(5000); + } + PRINTF("%x:%x:%x, %p, %p\n", cdbuffer[0], cdbuffer[1], cdbuffer[2], cdbuffer, cdcache); + found = 1; + + return 0; + } else found = 0; + + if (locked == 0) { + stopth = 1; + while (locked == 0) { usleep(5000); } + stopth = 0; + } + + // not found in cache + locked = 0; + pthread_mutex_lock(&mut); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mut); + + return 0; +} + +unsigned char* GetBThreaded() { + PRINTF("threadc %d\n", found); + + if (found == 1) return cdbuffer; + cdbuffer = cdcache[0].cr.buf + 12; + while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 || + btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 || + btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) { + if (locked == 1) return NULL; + usleep(5000); + } + if (cdcache[0].ret == -1) return NULL; + + return cdbuffer; +} + +void *CdrThread(void *arg) { + unsigned char curTime[3]; + int i; + + for (;;) { + locked = 1; + pthread_mutex_lock(&mut); + pthread_cond_wait(&cond, &mut); + + if (stopth == 2) pthread_exit(NULL); + // refill the buffer + cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0); + + memcpy(curTime, &cr.msf, 3); + + PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); + + for (i = 0; i < CacheSize; i++) { + memcpy(&cdcache[i].cr.msf, curTime, 3); + PRINTF("reading %d:%d:%d\n", curTime[0], curTime[1], curTime[2]); + cdcache[i].ret = ReadSector(&cdcache[i].cr); + + PRINTF("readed %x:%x:%x\n", cdcache[i].cr.buf[12], cdcache[i].cr.buf[13], cdcache[i].cr.buf[14]); + if (cdcache[i].ret == -1) break; + + curTime[2]++; + if (curTime[2] == 75) { + curTime[2] = 0; + curTime[1]++; + if (curTime[1] == 60) { + curTime[1] = 0; + curTime[0]++; + } + } + + if (stopth) break; + } + + pthread_mutex_unlock(&mut); + } + + return NULL; +} + +// read track +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// uses bcd format +long CDRreadTrack(unsigned char *time) { + if (!IsCdHandleOpen()) { + memset(cr.buf, 0, DATA_SIZE); + return 0; + } + + PRINTF("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2])); + + if (UseSubQ) memcpy(lastTime, time, 3); + subqread = 0; + + cr.msf.cdmsf_min0 = btoi(time[0]); + cr.msf.cdmsf_sec0 = btoi(time[1]); + cr.msf.cdmsf_frame0 = btoi(time[2]); + + return fReadTrack(); +} + +// return readed track +unsigned char *CDRgetBuffer(void) { + return fGetBuffer(); +} + +// plays cdda audio +// sector: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +// does NOT uses bcd format +long CDRplay(unsigned char *sector) { + long ret; + + if (!IsCdHandleOpen()) + return 0; + + // If play was called with the same time as the previous call, + // don't restart it. Of course, if play is called with a different + // track, stop playing the current stream. + if (playing) { + if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time) + return 0; + else + CDRstop(); + } + + initial_time = msf_to_lba(sector[0], sector[1], sector[2]); + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = PlayCDDA(sector); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (ret == 0) { + playing = 1; + return 0; + } + + return -1; +} + +// stops cdda audio +long CDRstop(void) { + long ret; + + if (!IsCdHandleOpen()) + return 0; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = StopCDDA(); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (ret == 0) { + playing = 0; + initial_time = 0; + + return 0; + } + + return -1; +} + +// reads cdr status +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: (only shell open supported) +// 0x00 - unknown +// 0x01 - error +// 0x04 - seek error +// 0x10 - shell open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + +long CDRgetStatus(struct CdrStat *stat) { + long ret; + + if (!IsCdHandleOpen()) + return -1; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetStatus(playing, stat); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +unsigned char *CDRgetBufferSub(void) { + static unsigned char *p = NULL; + + if (!UseSubQ) return NULL; + if (subqread) return p; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + p = ReadSub(lastTime); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + if (p != NULL) subqread = 1; + + return p; +} + +// read CDDA sector into buffer +long CDRreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) { + unsigned char msf[3] = {m, s, f}; + unsigned char *p; + + if (CDRreadTrack(msf) != 0) return -1; + + p = CDRgetBuffer(); + if (p == NULL) return -1; + + memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector + return 0; +} + +// get Track End Time +long CDRgetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) { + long ret; + + if (!IsCdHandleOpen()) return -1; + + if (ReadMode == THREADED) pthread_mutex_lock(&mut); + ret = GetTE(track, m, s, f); + if (ReadMode == THREADED) pthread_mutex_unlock(&mut); + + return ret; +} + +#ifndef _MACOSX + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDFCdrom"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFCdrom", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/DFCdrom"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgDFCdrom", arg, NULL); + exit(0); + } + return; + } + + fprintf(stderr, "cfgDFCdrom file not found!\n"); +} + +long CDRconfigure() { +#ifndef USE_NULL + ExecCfg("configure"); +#endif + return 0; +} + +void CDRabout() { + ExecCfg("about"); +} + +#endif + +long CDRtest(void) { +#ifndef USE_NULL + if (OpenCdHandle(CdromDev) == -1) + return -1; + CloseCdHandle(); +#endif + return 0; +} + +char *PSEgetLibName(void) { + return _(LibName); +} + +unsigned long PSEgetLibType(void) { + return PSE_LT_CDR; +} + +unsigned long PSEgetLibVersion(void) { + return 1 << 16; +} -- cgit v1.2.3