diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-07-08 00:23:38 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2010-07-08 00:23:38 +0000 |
| commit | e69ea176d835fa98912c99636a1a5cea8cbab105 (patch) | |
| tree | 350c3f53ccdda0a0603ac88a77037b15d8e71e5b /plugins/dfcdrom/cdr.c | |
| parent | 337765356b5fd420d3cab3349caa34eec2f98e65 (diff) | |
| download | pcsxr-e69ea176d835fa98912c99636a1a5cea8cbab105.tar.gz | |
dfcdrom: refactored for better portability.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@54325 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'plugins/dfcdrom/cdr.c')
| -rw-r--r-- | plugins/dfcdrom/cdr.c | 483 |
1 files changed, 469 insertions, 14 deletions
diff --git a/plugins/dfcdrom/cdr.c b/plugins/dfcdrom/cdr.c index b2e6606d..fd33dddf 100644 --- a/plugins/dfcdrom/cdr.c +++ b/plugins/dfcdrom/cdr.c @@ -1,27 +1,482 @@ /* - * Cdrom for Psemu Pro like Emulators + * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>. + * All Rights Reserved. * + * Based on: Cdrom for Psemu Pro like Emulators * By: linuzappz <linuzappz@hotmail.com> * + * 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 <http://www.gnu.org/licenses>. */ -#include "config.h" +#include "cdr.h" + +unsigned int msf_to_lba(char m, char s, char f) { + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; +} + +void lba_to_msf(unsigned int s, char *msf) { + s += CD_MSF_OFFSET; + + msf[0] = s / CD_FRAMES / CD_SECS; + s = s - msf[0] * CD_FRAMES * CD_SECS; + msf[1] = s / CD_FRAMES; + s = s - msf[1] * CD_FRAMES; + msf[2] = s; +} + +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]; +int cdHandle; +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); + +extern char *LibName; + +long CDRinit(void) { + cdHandle = -1; + thread = -1; + + return 0; +} + +long CDRshutdown(void) { + return 0; +} + +long CDRopen(void) { + LoadConf(); + + if (cdHandle > 0) + return 0; /* it's already open */ + + cdHandle = OpenCdHandle(CdromDev); + if (cdHandle == -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 = -1; + + playing = 0; + stopth = 0; + initial_time = 0; + + return 0; +} + +long CDRclose(void) { + if (cdHandle < 1) return 0; + + if (playing) CDRstop(); + + CloseCdHandle(cdHandle); + cdHandle = -1; + + if (thread != -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) { + if (cdHandle < 1) { + buffer[0] = 1; + buffer[1] = 1; + return 0; + } + + return GetTN(cdHandle, buffer); +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +long CDRgetTD(unsigned char track, unsigned char *buffer) { + if (cdHandle < 1) { + memset(buffer + 1, 0, 3); + return 0; + } + + return GetTD(cdHandle, track, buffer); +} + +// normal reading +long ReadNormal() { + if (ReadSector(cdHandle, &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); -#ifdef ENABLE_NLS -#include <libintl.h> -#include <locale.h> -#define _(x) gettext(x) -#define N_(x) (x) -#else -#define _(x) (x) -#define N_(x) (x) + 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(cdHandle, &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 (cdHandle < 1) { + 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) { + if (cdHandle < 1) + 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 (PlayCDDA(cdHandle, sector) == 0) { + playing = 1; + return 0; + } + + return -1; +} + +// stops cdda audio +long CDRstop(void) { + if (cdHandle < 1) + return 0; + + if (StopCDDA(cdHandle) == 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) { + if (cdHandle < 1) + return -1; + + return GetStatus(cdHandle, playing, stat); +} + +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(cdHandle, 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) { + if (cdHandle < 1) return -1; + return GetTE(cdHandle, track, m, s, f); +} + +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; +} -#if defined (__linux__) -#include "cdr-linux.c" -#else -#include "cdr-null.c" +void CDRabout() { + ExecCfg("about"); +} + +long CDRtest(void) { +#ifndef USE_NULL + cdHandle = open(CdromDev, O_RDONLY); + if (cdHandle == -1) + return -1; + close(cdHandle); + cdHandle = -1; #endif + return 0; +} char *PSEgetLibName(void) { return _(LibName); |
