pcsxr-1.9.92
[pcsx_rearmed.git] / plugins / dfcdrom / cdr.c
CommitLineData
ef79bbde
P
1/*
2 * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
3 * All Rights Reserved.
4 *
5 * Based on: Cdrom for Psemu Pro like Emulators
6 * By: linuzappz <linuzappz@hotmail.com>
7 *
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.
12 *
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.
17 *
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>.
20 */
21
22#include "cdr.h"
23
24#ifndef USE_NULL
25static char *LibName = N_("CD-ROM Drive Reader");
26#else
27static char *LibName = N_("CDR NULL Plugin");
28#endif
29
30int initial_time = 0;
31
32pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
33pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
34
35CacheData *cdcache;
36unsigned char *cdbuffer;
37int cacheaddr;
38
39crdata cr;
40
41unsigned char lastTime[3];
42pthread_t thread;
43int subqread;
44volatile int stopth, found, locked, playing;
45
46long (*ReadTrackT[])() = {
47 ReadNormal,
48 ReadThreaded,
49};
50
51unsigned char* (*GetBufferT[])() = {
52 GetBNormal,
53 GetBThreaded,
54};
55
56long (*fReadTrack)();
57unsigned char* (*fGetBuffer)();
58
59void *CdrThread(void *arg);
60
61long CDRinit(void) {
62 thread = (pthread_t)-1;
63 return 0;
64}
65
66long CDRshutdown(void) {
67 return 0;
68}
69
70long CDRopen(void) {
71 LoadConf();
72
73#ifndef _MACOSX
74 if (IsCdHandleOpen())
75 return 0; // it's already open
76#endif
77
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);
80 }
81
82 fReadTrack = ReadTrackT[ReadMode];
83 fGetBuffer = GetBufferT[ReadMode];
84
85 if (ReadMode == THREADED) {
86 cdcache = (CacheData *)malloc(CacheSize * sizeof(CacheData));
87 if (cdcache == NULL) return -1;
88 memset(cdcache, 0, CacheSize * sizeof(CacheData));
89
90 found = 0;
91 } else {
92 cdbuffer = cr.buf + 12; /* skip sync data */
93 }
94
95 if (ReadMode == THREADED) {
96 pthread_attr_t attr;
97
98 pthread_mutex_init(&mut, NULL);
99 pthread_cond_init(&cond, NULL);
100 locked = 0;
101
102 pthread_attr_init(&attr);
103 pthread_create(&thread, &attr, CdrThread, NULL);
104
105 cacheaddr = -1;
106 } else thread = (pthread_t)-1;
107
108 playing = 0;
109 stopth = 0;
110 initial_time = 0;
111
112 return 0;
113}
114
115long CDRclose(void) {
116 if (!IsCdHandleOpen()) return 0;
117
118 if (playing) CDRstop();
119
120 CloseCdHandle();
121
122 if (thread != (pthread_t)-1) {
123 if (locked == 0) {
124 stopth = 1;
125 while (locked == 0) usleep(5000);
126 }
127
128 stopth = 2;
129 pthread_mutex_lock(&mut);
130 pthread_cond_signal(&cond);
131 pthread_mutex_unlock(&mut);
132
133 pthread_join(thread, NULL);
134 pthread_mutex_destroy(&mut);
135 pthread_cond_destroy(&cond);
136 }
137
138 if (ReadMode == THREADED) {
139 free(cdcache);
140 }
141
142 return 0;
143}
144
145// return Starting and Ending Track
146// buffer:
147// byte 0 - start track
148// byte 1 - end track
149long CDRgetTN(unsigned char *buffer) {
150 long ret;
151
152 if (!IsCdHandleOpen()) {
153 buffer[0] = 1;
154 buffer[1] = 1;
155 return 0;
156 }
157
158 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
159 ret = GetTN(buffer);
160 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
161
162 return ret;
163}
164
165// return Track Time
166// buffer:
167// byte 0 - frame
168// byte 1 - second
169// byte 2 - minute
170long CDRgetTD(unsigned char track, unsigned char *buffer) {
171 long ret;
172
173 if (!IsCdHandleOpen()) {
174 memset(buffer + 1, 0, 3);
175 return 0;
176 }
177
178 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
179 ret = GetTD(track, buffer);
180 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
181
182 return ret;
183}
184
185// normal reading
186long ReadNormal() {
187 if (ReadSector(&cr) == -1)
188 return -1;
189
190 return 0;
191}
192
193unsigned char* GetBNormal() {
194 return cdbuffer;
195}
196
197// threaded reading (with cache)
198long ReadThreaded() {
199 int addr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);
200 int i;
201
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) {
209 if (locked == 1) {
210 if (cdcache[i].ret == 0) break;
211 return -1;
212 }
213 usleep(5000);
214 }
215 PRINTF("%x:%x:%x, %p, %p\n", cdbuffer[0], cdbuffer[1], cdbuffer[2], cdbuffer, cdcache);
216 found = 1;
217
218 return 0;
219 } else found = 0;
220
221 if (locked == 0) {
222 stopth = 1;
223 while (locked == 0) { usleep(5000); }
224 stopth = 0;
225 }
226
227 // not found in cache
228 locked = 0;
229 pthread_mutex_lock(&mut);
230 pthread_cond_signal(&cond);
231 pthread_mutex_unlock(&mut);
232
233 return 0;
234}
235
236unsigned char* GetBThreaded() {
237 PRINTF("threadc %d\n", found);
238
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;
245 usleep(5000);
246 }
247 if (cdcache[0].ret == -1) return NULL;
248
249 return cdbuffer;
250}
251
252void *CdrThread(void *arg) {
253 unsigned char curTime[3];
254 int i;
255
256 for (;;) {
257 locked = 1;
258 pthread_mutex_lock(&mut);
259 pthread_cond_wait(&cond, &mut);
260
261 if (stopth == 2) pthread_exit(NULL);
262 // refill the buffer
263 cacheaddr = msf_to_lba(cr.msf.cdmsf_min0, cr.msf.cdmsf_sec0, cr.msf.cdmsf_frame0);
264
265 memcpy(curTime, &cr.msf, 3);
266
267 PRINTF("start thc %d:%d:%d\n", curTime[0], curTime[1], curTime[2]);
268
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);
273
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;
276
277 curTime[2]++;
278 if (curTime[2] == 75) {
279 curTime[2] = 0;
280 curTime[1]++;
281 if (curTime[1] == 60) {
282 curTime[1] = 0;
283 curTime[0]++;
284 }
285 }
286
287 if (stopth) break;
288 }
289
290 pthread_mutex_unlock(&mut);
291 }
292
293 return NULL;
294}
295
296// read track
297// time:
298// byte 0 - minute
299// byte 1 - second
300// byte 2 - frame
301// uses bcd format
302long CDRreadTrack(unsigned char *time) {
303 if (!IsCdHandleOpen()) {
304 memset(cr.buf, 0, DATA_SIZE);
305 return 0;
306 }
307
308 PRINTF("CDRreadTrack %d:%d:%d\n", btoi(time[0]), btoi(time[1]), btoi(time[2]));
309
310 if (UseSubQ) memcpy(lastTime, time, 3);
311 subqread = 0;
312
313 cr.msf.cdmsf_min0 = btoi(time[0]);
314 cr.msf.cdmsf_sec0 = btoi(time[1]);
315 cr.msf.cdmsf_frame0 = btoi(time[2]);
316
317 return fReadTrack();
318}
319
320// return readed track
321unsigned char *CDRgetBuffer(void) {
322 return fGetBuffer();
323}
324
325// plays cdda audio
326// sector:
327// byte 0 - minute
328// byte 1 - second
329// byte 2 - frame
330// does NOT uses bcd format
331long CDRplay(unsigned char *sector) {
332 long ret;
333
334 if (!IsCdHandleOpen())
335 return 0;
336
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.
340 if (playing) {
341 if (msf_to_lba(sector[0], sector[1], sector[2]) == initial_time)
342 return 0;
343 else
344 CDRstop();
345 }
346
347 initial_time = msf_to_lba(sector[0], sector[1], sector[2]);
348
349 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
350 ret = PlayCDDA(sector);
351 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
352
353 if (ret == 0) {
354 playing = 1;
355 return 0;
356 }
357
358 return -1;
359}
360
361// stops cdda audio
362long CDRstop(void) {
363 long ret;
364
365 if (!IsCdHandleOpen())
366 return 0;
367
368 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
369 ret = StopCDDA();
370 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
371
372 if (ret == 0) {
373 playing = 0;
374 initial_time = 0;
375
376 return 0;
377 }
378
379 return -1;
380}
381
382// reads cdr status
383// type:
384// 0x00 - unknown
385// 0x01 - data
386// 0x02 - audio
387// 0xff - no cdrom
388// status: (only shell open supported)
389// 0x00 - unknown
390// 0x01 - error
391// 0x04 - seek error
392// 0x10 - shell open
393// 0x20 - reading
394// 0x40 - seeking
395// 0x80 - playing
396// time:
397// byte 0 - minute
398// byte 1 - second
399// byte 2 - frame
400
401long CDRgetStatus(struct CdrStat *stat) {
402 long ret;
403
404 if (!IsCdHandleOpen())
405 return -1;
406
407 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
408 ret = GetStatus(playing, stat);
409 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
410
411 return ret;
412}
413
414unsigned char *CDRgetBufferSub(void) {
415 static unsigned char *p = NULL;
416
417 if (!UseSubQ) return NULL;
418 if (subqread) return p;
419
420 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
421 p = ReadSub(lastTime);
422 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
423
424 if (p != NULL) subqread = 1;
425
426 return p;
427}
428
429// read CDDA sector into buffer
430long CDRreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) {
431 unsigned char msf[3] = {m, s, f};
432 unsigned char *p;
433
434 if (CDRreadTrack(msf) != 0) return -1;
435
436 p = CDRgetBuffer();
437 if (p == NULL) return -1;
438
439 memcpy(buffer, p - 12, CD_FRAMESIZE_RAW); // copy from the beginning of the sector
440 return 0;
441}
442
443// get Track End Time
444long CDRgetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) {
445 long ret;
446
447 if (!IsCdHandleOpen()) return -1;
448
449 if (ReadMode == THREADED) pthread_mutex_lock(&mut);
450 ret = GetTE(track, m, s, f);
451 if (ReadMode == THREADED) pthread_mutex_unlock(&mut);
452
453 return ret;
454}
455
456#ifndef _MACOSX
457
458void ExecCfg(char *arg) {
459 char cfg[256];
460 struct stat buf;
461
462 strcpy(cfg, "./cfgDFCdrom");
463 if (stat(cfg, &buf) != -1) {
464 if (fork() == 0) {
465 execl(cfg, "cfgDFCdrom", arg, NULL);
466 exit(0);
467 }
468 return;
469 }
470
471 strcpy(cfg, "./cfg/DFCdrom");
472 if (stat(cfg, &buf) != -1) {
473 if (fork() == 0) {
474 execl(cfg, "cfgDFCdrom", arg, NULL);
475 exit(0);
476 }
477 return;
478 }
479
480 fprintf(stderr, "cfgDFCdrom file not found!\n");
481}
482
483long CDRconfigure() {
484#ifndef USE_NULL
485 ExecCfg("configure");
486#endif
487 return 0;
488}
489
490void CDRabout() {
491 ExecCfg("about");
492}
493
494#endif
495
496long CDRtest(void) {
497#ifndef USE_NULL
498 if (OpenCdHandle(CdromDev) == -1)
499 return -1;
500 CloseCdHandle();
501#endif
502 return 0;
503}
504
505char *PSEgetLibName(void) {
506 return _(LibName);
507}
508
509unsigned long PSEgetLibType(void) {
510 return PSE_LT_CDR;
511}
512
513unsigned long PSEgetLibVersion(void) {
514 return 1 << 16;
515}