2 * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
5 * Based on: Cdrom for Psemu Pro like Emulators
6 * By: linuzappz <linuzappz@hotmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses>.
25 static char *LibName = N_("CD-ROM Drive Reader");
27 static char *LibName = N_("CDR NULL Plugin");
32 pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
33 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
36 unsigned char *cdbuffer;
41 unsigned char lastTime[3];
44 volatile int stopth, found, locked, playing;
46 long (*ReadTrackT[])() = {
51 unsigned char* (*GetBufferT[])() = {
57 unsigned char* (*fGetBuffer)();
59 void *CdrThread(void *arg);
62 thread = (pthread_t)-1;
66 long CDRshutdown(void) {
75 return 0; // it's already open
78 if (OpenCdHandle(CdromDev) == -1) { // if we can't open the cdrom we'll works as a null plugin
79 fprintf(stderr, "CDR: Could not open %s\n", CdromDev);
82 fReadTrack = ReadTrackT[ReadMode];
83 fGetBuffer = GetBufferT[ReadMode];
85 if (ReadMode == THREADED) {
86 cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData));
87 if (cdcache == NULL) return -1;
88 memset(cdcache, 0, CacheSize * sizeof(CacheData));
92 cdbuffer = cr.buf + 12; /* skip sync data */
95 if (ReadMode == THREADED) {
98 pthread_mutex_init(&mut, NULL);
99 pthread_cond_init(&cond, NULL);
102 pthread_attr_init(&attr);
103 pthread_create(&thread, &attr, CdrThread, NULL);
106 } else thread = (pthread_t)-1;
115 long CDRclose(void) {
116 if (!IsCdHandleOpen()) return 0;
118 if (playing) CDRstop();
122 if (thread != (pthread_t)-1) {
125 while (locked == 0) usleep(5000);
129 pthread_mutex_lock(&mut);
130 pthread_cond_signal(&cond);
131 pthread_mutex_unlock(&mut);
133 pthread_join(thread, NULL);
134 pthread_mutex_destroy(&mut);
135 pthread_cond_destroy(&cond);
138 if (ReadMode == THREADED) {
145 // return Starting and Ending Track
147 // byte 0 - start track
148 // byte 1 - end track
149 long CDRgetTN(unsigned char *buffer) {
152 if (!IsCdHandleOpen()) {
158 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
160 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
170 long CDRgetTD(unsigned char track, unsigned char *buffer) {
173 if (!IsCdHandleOpen()) {
174 memset(buffer + 1, 0, 3);
178 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
179 ret = GetTD(track, buffer);
180 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
187 if (ReadSector(&cr) == -1)
193 unsigned char* GetBNormal() {
197 // threaded reading (with cache)
198 long ReadThreaded() {
199 int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);
202 if (addr >= cacheaddr && addr < (cacheaddr + CacheSize) && cacheaddr != -1) {
203 i = addr - cacheaddr;
204 PRINTF("found %d\n", (addr - cacheaddr));
205 cdbuffer = cdcache[i].cr.buf + 12;
206 while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 ||
207 btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 ||
208 btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) {
210 if (cdcache[i].ret == 0) break;
215 PRINTF("%x:%x:%x, %p, %p\n", cdbuffer[0], cdbuffer[1], cdbuffer[2], cdbuffer, cdcache);
223 while (locked == 0) { usleep(5000); }
227 // not found in cache
229 pthread_mutex_lock(&mut);
230 pthread_cond_signal(&cond);
231 pthread_mutex_unlock(&mut);
236 unsigned char* GetBThreaded() {
237 PRINTF("threadc %d\n", found);
239 if (found == 1) return cdbuffer;
240 cdbuffer = cdcache[0].cr.buf + 12;
241 while (btoi(cdbuffer[0]) != cr.msf.cdmsf_min0 ||
242 btoi(cdbuffer[1]) != cr.msf.cdmsf_sec0 ||
243 btoi(cdbuffer[2]) != cr.msf.cdmsf_frame0) {
244 if (locked == 1) return NULL;
247 if (cdcache[0].ret == -1) return NULL;
252 void *CdrThread(void *arg) {
253 unsigned char curTime[3];
258 pthread_mutex_lock(&mut);
259 pthread_cond_wait(&cond, &mut);
261 if (stopth == 2) pthread_exit(NULL);
263 cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);
265 memcpy(curTime, &cr.msf, 3);
267 PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]);
269 for (i = 0; i < CacheSize; i++) {
270 memcpy(&cdcache[i].cr.msf, curTime, 3);
271 PRINTF("reading %d:%d:%d\n", curTime[0], curTime[1], curTime[2]);
272 cdcache[i].ret = ReadSector(&cdcache[i].cr);
274 PRINTF("readed %x:%x:%x\n", cdcache[i].cr.buf[12], cdcache[i].cr.buf[13], cdcache[i].cr.buf[14]);
275 if (cdcache[i].ret == -1) break;
278 if (curTime[2] == 75) {
281 if (curTime[1] == 60) {
290 pthread_mutex_unlock(&mut);
302 long CDRreadTrack(unsigned char *time) {
303 if (!IsCdHandleOpen()) {
304 memset(cr.buf, 0, DATA_SIZE);
308 PRINTF("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2]));
310 if (UseSubQ) memcpy(lastTime, time, 3);
313 cr.msf.cdmsf_min0 = btoi(time[0]);
314 cr.msf.cdmsf_sec0 = btoi(time[1]);
315 cr.msf.cdmsf_frame0 = btoi(time[2]);
320 // return readed track
321 unsigned char *CDRgetBuffer(void) {
330 // does NOT uses bcd format
331 long CDRplay(unsigned char *sector) {
334 if (!IsCdHandleOpen())
337 // If play was called with the same time as the previous call,
338 // don't restart it. Of course, if play is called with a different
339 // track, stop playing the current stream.
341 if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time)
347 initial_time = msf_to_lba(sector[0], sector[1], sector[2]);
349 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
350 ret = PlayCDDA(sector);
351 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
365 if (!IsCdHandleOpen())
368 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
370 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
388 // status: (only shell open supported)
401 long CDRgetStatus(struct CdrStat *stat) {
404 if (!IsCdHandleOpen())
407 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
408 ret = GetStatus(playing, stat);
409 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
414 unsigned char *CDRgetBufferSub(void) {
415 static unsigned char *p = NULL;
417 if (!UseSubQ) return NULL;
418 if (subqread) return p;
420 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
421 p = ReadSub(lastTime);
422 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
424 if (p != NULL) subqread = 1;
429 // read CDDA sector into buffer
430 long CDRreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) {
431 unsigned char msf[3] = {m, s, f};
434 if (CDRreadTrack(msf) != 0) return -1;
437 if (p == NULL) return -1;
439 memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector
443 // get Track End Time
444 long CDRgetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) {
447 if (!IsCdHandleOpen()) return -1;
449 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
450 ret = GetTE(track, m, s, f);
451 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
458 void ExecCfg(char *arg) {
462 strcpy(cfg, "./cfgDFCdrom");
463 if (stat(cfg, &buf) != -1) {
465 execl(cfg, "cfgDFCdrom", arg, NULL);
471 strcpy(cfg, "./cfg/DFCdrom");
472 if (stat(cfg, &buf) != -1) {
474 execl(cfg, "cfgDFCdrom", arg, NULL);
480 fprintf(stderr, "cfgDFCdrom file not found!\n");
483 long CDRconfigure() {
485 ExecCfg("configure");
498 if (OpenCdHandle(CdromDev) == -1)
505 char *PSEgetLibName(void) {
509 unsigned long PSEgetLibType(void) {
513 unsigned long PSEgetLibVersion(void) {