1 /***************************************************************************************
3 * CD drive processor & CD-DA fader
5 * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX)
7 * Redistribution and use of this code or any derivative works are permitted
8 * provided that the following conditions are met:
10 * - Redistributions may not be sold, nor may they be used in a commercial
11 * product or activity.
13 * - Redistributions that are modified from the original source must include the
14 * complete source code, including the source code for all components used by a
15 * binary built from the modified sources. However, as a special exception, the
16 * source code distributed need not include anything that is normally distributed
17 * (in either source or binary form) with the major components (compiler, kernel,
18 * and so on) of the operating system on which the executable runs, unless that
19 * component itself accompanies the executable.
21 * - Redistributions must reproduce the above copyright notice, this list of
22 * conditions and the following disclaimer in the documentation and/or other
23 * materials provided with the distribution.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
37 ****************************************************************************************/
39 #include "../pico_int.h"
40 #include "genplus_macros.h"
45 #define SUPPORTED_EXT 20
47 #define SUPPORTED_EXT 10
52 /* BCD conversion lookup tables */
53 static const uint8 lut_BCD_8[100] =
55 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
56 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
57 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
58 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
59 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
60 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
61 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
62 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
63 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
64 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
67 static const uint16 lut_BCD_16[100] =
69 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
70 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
71 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
72 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
73 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
74 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
75 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609,
76 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
77 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
78 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
82 static const uint16 toc_snatcher[21] =
84 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681,
85 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485,
89 static const uint16 toc_lunar[52] =
91 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870,
92 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263,
93 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205,
94 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549,
95 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132,
99 static const uint32 toc_shadow[15] =
101 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792,
102 11637, 2547, 2521, 3856, 900
105 static const uint32 toc_dungeon[13] =
107 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
111 static const uint32 toc_ffight[26] =
113 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764,
114 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024,
115 14562, 10320, 8627, 3795, 3047
118 static const uint32 toc_ffightj[29] =
120 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763,
121 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026,
122 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052
125 /* supported WAVE file header (16-bit stereo samples @44.1kHz) */
126 static const unsigned char waveHeader[32] =
128 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
129 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61
133 #ifdef DISABLE_MANY_OGG_OPEN_FILES
134 static void ogg_free(int i)
136 /* clear OGG file descriptor to prevent file from being closed */
137 cdd.toc.tracks[i].vf.datasource = NULL;
139 /* close VORBIS file structure */
140 ov_clear(&cdd.toc.tracks[i].vf);
142 /* indicates that the track is a seekable VORBIS file */
143 cdd.toc.tracks[i].vf.seekable = 1;
145 /* reset file reading position */
146 fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET);
153 /* reset cycle counter */
156 /* reset drive access latency */
159 /* reset track index */
162 /* reset logical block address */
166 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
168 /* reset CD-DA fader (full volume) */
171 /* clear CD-DA output */
172 cdd.audio[0] = cdd.audio[1] = 0;
175 /* FIXME: use cdd_read_audio() instead */
176 static void cdd_change_track(int index, int lba)
178 int i, base, lba_offset, lb_len;
180 for (i = index; i > 0; i--)
181 if (cdd.toc.tracks[i].fd != NULL)
184 Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd;
185 base = cdd.toc.tracks[index].offset;
186 lba_offset = lba - cdd.toc.tracks[index].start;
187 lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start;
189 elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base);
191 cdda_start_play(base, lba_offset, lb_len);
194 int cdd_context_save(uint8 *state)
198 save_param(&cdd.cycles, sizeof(cdd.cycles));
199 save_param(&cdd.latency, sizeof(cdd.latency));
200 save_param(&cdd.index, sizeof(cdd.index));
201 save_param(&cdd.lba, sizeof(cdd.lba));
202 save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
203 save_param(&cdd.volume, sizeof(cdd.volume));
204 save_param(&cdd.status, sizeof(cdd.status));
209 int cdd_context_load(uint8 *state)
215 #ifdef DISABLE_MANY_OGG_OPEN_FILES
216 /* close previous track VORBIS file structure to save memory */
217 if (cdd.toc.tracks[cdd.index].vf.datasource)
224 load_param(&cdd.cycles, sizeof(cdd.cycles));
225 load_param(&cdd.latency, sizeof(cdd.latency));
226 load_param(&cdd.index, sizeof(cdd.index));
227 load_param(&cdd.lba, sizeof(cdd.lba));
228 load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
229 load_param(&cdd.volume, sizeof(cdd.volume));
230 load_param(&cdd.status, sizeof(cdd.status));
232 /* adjust current LBA within track limit */
234 if (lba < cdd.toc.tracks[cdd.index].start)
236 lba = cdd.toc.tracks[cdd.index].start;
239 /* seek to current track position */
243 if (cdd.toc.tracks[0].fd)
245 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
249 else if (cdd.toc.tracks[cdd.index].vf.seekable)
251 #ifdef DISABLE_MANY_OGG_OPEN_FILES
252 /* VORBIS file need to be opened first */
253 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
255 /* VORBIS AUDIO track */
256 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
260 else if (cdd.toc.tracks[cdd.index].fd)
262 /* PCM AUDIO track */
263 fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
268 cdd_change_track(cdd.index, lba);
275 int cdd_context_load_old(uint8 *state)
277 memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
281 int cdd_load(const char *filename, int type)
286 /* first unmount any loaded disc */
289 /* genplus parses cue here, in PD we use our own parser */
290 ret = load_cd_image(filename, &type);
294 /* read first 16 bytes */
295 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
297 /* look for valid CD image ID string */
298 if (memcmp("SEGADISCSYSTEM", header, 14))
300 /* if not found, read next 16 bytes */
301 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
303 /* look again for valid CD image ID string */
304 if (memcmp("SEGADISCSYSTEM", header, 14))
306 elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
307 /* assume bin without security code */
310 /* BIN format (2352 bytes data blocks) */
311 cdd.sectorSize = 2352;
315 /* ISO format (2048 bytes data blocks) */
316 cdd.sectorSize = 2048;
319 ret = (type == CT_BIN) ? 2352 : 2048;
320 if (ret != cdd.sectorSize)
321 elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
323 /* read CD image header + security code */
324 pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
326 /* Simulate audio tracks if none found */
327 if (cdd.toc.last == 1)
329 /* Some games require exact TOC infos */
330 if (strstr(header + 0x180,"T-95035") != NULL)
333 cdd.toc.last = cdd.toc.end = 0;
336 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
337 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
338 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
341 while (cdd.toc.last < 21);
343 else if (strstr(header + 0x180,"T-127015") != NULL)
345 /* Lunar - The Silver Star */
346 cdd.toc.last = cdd.toc.end = 0;
349 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
350 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
351 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
354 while (cdd.toc.last < 52);
356 else if (strstr(header + 0x180,"T-113045") != NULL)
358 /* Shadow of the Beast II */
359 cdd.toc.last = cdd.toc.end = 0;
362 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
363 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
364 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
367 while (cdd.toc.last < 15);
369 else if (strstr(header + 0x180,"T-143025") != NULL)
371 /* Dungeon Explorer */
372 cdd.toc.last = cdd.toc.end = 0;
375 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
376 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
377 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
380 while (cdd.toc.last < 13);
382 else if (strstr(header + 0x180,"MK-4410") != NULL)
384 /* Final Fight CD (USA, Europe) */
385 cdd.toc.last = cdd.toc.end = 0;
388 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
389 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
390 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
393 while (cdd.toc.last < 26);
395 else if (strstr(header + 0x180,"G-6013") != NULL)
397 /* Final Fight CD (Japan) */
398 cdd.toc.last = cdd.toc.end = 0;
401 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
402 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
403 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
406 while (cdd.toc.last < 29);
411 /* default TOC (99 tracks & 2s per audio tracks) */
414 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
415 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
416 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
419 while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
425 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
434 int was_loaded = cdd.loaded;
440 /* close CD tracks */
441 if (cdd.toc.tracks[0].fd)
443 pm_close(cdd.toc.tracks[0].fd);
444 cdd.toc.tracks[0].fd = NULL;
447 for (i = 1; i < cdd.toc.last; i++)
450 if (cdd.toc.tracks[i].vf.datasource)
452 /* close VORBIS file (if still opened) */
453 ov_clear(&cdd.toc.tracks[i].vf);
457 if (cdd.toc.tracks[i].fd)
460 if (Pico_mcd->cdda_type == CT_MP3)
461 fclose(cdd.toc.tracks[i].fd);
463 pm_close(cdd.toc.tracks[0].fd);
465 /* detect single file images */
466 if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
479 memset(&cdd.toc, 0x00, sizeof(cdd.toc));
481 /* unknown CD image file format */
487 void cdd_read_data(uint8 *dst)
489 /* only read DATA track sectors */
490 if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
493 if (cdd.sectorSize == 2352)
495 /* skip 16-byte header */
496 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
499 /* read sector data (Mode 1 = 2048 bytes) */
500 pm_read(dst, 2048, cdd.toc.tracks[0].fd);
505 void cdd_read_audio(unsigned int samples)
507 /* previous audio outputs */
508 int16 l = cdd.audio[0];
509 int16 r = cdd.audio[1];
511 /* get number of internal clocks (samples) needed */
512 samples = blip_clocks_needed(blip[0], samples);
514 /* audio track playing ? */
515 if (!Pico_mcd->regs[0x36>>1].byte.h && cdd.toc.tracks[cdd.index].fd)
519 /* current CD-DA fader volume */
520 int curVol = cdd.volume;
522 /* CD-DA fader volume setup (0-1024) */
523 int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
525 /* read samples from current block */
527 if (cdd.toc.tracks[cdd.index].vf.datasource)
530 int16 *ptr = (int16 *) (cdc.ram);
531 samples = samples * 4;
532 while (done < samples)
534 len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
544 /* process 16-bit (host-endian) stereo samples */
545 for (i=0; i<samples; i++)
547 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
548 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
549 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
552 delta = ((ptr[0] * mul) / 1024) - l;
555 blip_add_delta_fast(blip[0], i, delta);
558 delta = ((ptr[0] * mul) / 1024) - r;
561 blip_add_delta_fast(blip[1], i, delta);
563 /* update CD-DA fader volume (one step/sample) */
569 else if (curVol > endVol)
576 /* audio will remain muted until next setup */
585 int16 *ptr = (int16 *) (cdc.ram);
587 uint8 *ptr = cdc.ram;
589 fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
591 /* process 16-bit (little-endian) stereo samples */
592 for (i=0; i<samples; i++)
594 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
595 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
596 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
600 delta = ((ptr[0] * mul) / 1024) - l;
603 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
607 blip_add_delta_fast(blip[0], i, delta);
611 delta = ((ptr[0] * mul) / 1024) - r;
614 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
618 blip_add_delta_fast(blip[1], i, delta);
620 /* update CD-DA fader volume (one step/sample) */
626 else if (curVol > endVol)
633 /* audio will remain muted until next setup */
639 /* save current CD-DA fader volume */
642 /* save last audio output for next frame */
648 /* no audio output */
649 if (l) blip_add_delta_fast(blip[0], 0, -l);
650 if (r) blip_add_delta_fast(blip[1], 0, -r);
652 /* save audio output for next frame */
657 /* end of Blip Buffer timeframe */
658 blip_end_frame(blip[0], samples);
659 blip_end_frame(blip[1], samples);
664 void cdd_update(void)
667 error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
671 if (cdd.status == CD_SEEK)
681 cdd.status = CD_READY;
685 else if (cdd.status == CD_PLAY)
697 /* DATA sector header (CD-ROM Mode 1) */
699 uint32 msf = cdd.lba + 150;
700 header[0] = lut_BCD_8[(msf / 75) / 60];
701 header[1] = lut_BCD_8[(msf / 75) % 60];
702 header[2] = lut_BCD_8[(msf % 75)];
705 /* data track sector read is controlled by CDC */
706 cdd.lba += cdc_decoder_update(header);
708 else if (cdd.index < cdd.toc.last)
710 uint8 header[4] = { 0, };
712 /* check against audio track start index */
713 if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
715 /* audio track playing */
716 Pico_mcd->regs[0x36>>1].byte.h = 0x00;
719 /* audio blocks are still sent to CDC as well as CD DAC/Fader */
720 cdc_decoder_update(header);
722 /* next audio block is automatically read */
732 /* check end of current track */
733 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
736 #ifdef DISABLE_MANY_OGG_OPEN_FILES
737 /* close previous track VORBIS file structure to save memory */
738 if (cdd.toc.tracks[cdd.index].vf.datasource)
744 /* play next track */
747 /* PAUSE between tracks */
748 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
750 /* seek to next audio track start */
752 if (cdd.toc.tracks[cdd.index].vf.seekable)
754 #ifdef DISABLE_MANY_OGG_OPEN_FILES
755 /* VORBIS file need to be opened first */
756 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
758 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
763 if (cdd.toc.tracks[cdd.index].fd)
765 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
769 cdd_change_track(cdd.index, cdd.lba);
776 else if (cdd.status == CD_SCAN)
778 /* fast-forward or fast-rewind */
779 cdd.lba += cdd.scanOffset;
781 /* check current track limits */
782 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
785 #ifdef DISABLE_MANY_OGG_OPEN_FILES
786 /* close previous track VORBIS file structure to save memory */
787 if (cdd.toc.tracks[cdd.index].vf.datasource)
796 /* skip directly to track start position */
797 cdd.lba = cdd.toc.tracks[cdd.index].start;
799 /* AUDIO track playing ? */
800 if (cdd.status == CD_PLAY)
802 Pico_mcd->regs[0x36>>1].byte.h = 0x00;
805 else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
808 #ifdef DISABLE_MANY_OGG_OPEN_FILES
809 /* close previous track VORBIS file structure to save memory */
810 if (cdd.toc.tracks[cdd.index].vf.datasource)
820 /* skip directly to track end position */
821 cdd.lba = cdd.toc.tracks[cdd.index].end;
824 /* check disc limits */
830 else if (cdd.index >= cdd.toc.last)
832 /* no AUDIO track playing */
833 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
836 cdd.index = cdd.toc.last;
837 cdd.lba = cdd.toc.end;
842 /* seek to current block */
845 /* no AUDIO track playing */
846 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
849 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
852 else if (cdd.toc.tracks[cdd.index].vf.seekable)
854 #ifdef DISABLE_MANY_OGG_OPEN_FILES
855 /* check if a new track is being played */
856 if (!cdd.toc.tracks[cdd.index].vf.datasource)
858 /* VORBIS file need to be opened first */
859 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
862 /* VORBIS AUDIO track */
863 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
867 else if (cdd.toc.tracks[cdd.index].fd)
869 /* PCM AUDIO track */
870 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
875 cdd_change_track(cdd.index, cdd.lba);
881 #define set_reg16(r, v) { \
883 Pico_mcd->s68k_regs[(r)] = _v >> 8; \
884 Pico_mcd->s68k_regs[(r)+1] = _v; \
887 void cdd_process(void)
889 /* Process CDD command */
890 switch (Pico_mcd->regs[0x42>>1].byte.h & 0x0f)
892 case 0x00: /* Drive Status */
894 /* RS1-RS8 normally unchanged */
895 Pico_mcd->regs[0x38>>1].byte.h = cdd.status;
897 /* unless RS1 indicated invalid track infos */
898 if (Pico_mcd->regs[0x38>>1].byte.l == 0x0f)
900 /* and SEEK has ended */
901 if (cdd.status != CD_SEEK)
903 /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */
904 Pico_mcd->regs[0x38>>1].byte.l = 0x02;
905 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
911 case 0x01: /* Stop Drive */
914 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
916 /* no audio track playing */
917 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
919 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
920 set_reg16(0x38, 0x0000);
921 set_reg16(0x3a, 0x0000);
922 set_reg16(0x3c, 0x0000);
923 set_reg16(0x3e, 0x0000);
924 set_reg16(0x40, 0x000f);
928 case 0x02: /* Read TOC */
930 /* Infos automatically retrieved by CDD processor from Q-Channel */
931 /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
932 switch (Pico_mcd->regs[0x44>>1].byte.l)
934 case 0x00: /* Current Absolute Time (MM:SS:FF) */
936 int lba = cdd.lba + 150;
937 set_reg16(0x38, cdd.status << 8);
938 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
939 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
940 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
941 Pico_mcd->regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
945 case 0x01: /* Current Track Relative Time (MM:SS:FF) */
947 int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
948 set_reg16(0x38, (cdd.status << 8) | 0x01);
949 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
950 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
951 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
952 Pico_mcd->regs[0x40>>1].byte.h = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
956 case 0x02: /* Current Track Number */
958 set_reg16(0x38, (cdd.status << 8) | 0x02);
959 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
960 set_reg16(0x3c, 0x0000);
961 set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
962 Pico_mcd->regs[0x40>>1].byte.h = 0x00;
966 case 0x03: /* Total length (MM:SS:FF) */
968 int lba = cdd.toc.end + 150;
969 set_reg16(0x38, (cdd.status << 8) | 0x03);
970 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
971 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
972 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
973 Pico_mcd->regs[0x40>>1].byte.h = 0x00;
977 case 0x04: /* First & Last Track Numbers */
979 set_reg16(0x38, (cdd.status << 8) | 0x04);
980 set_reg16(0x3a, 0x0001);
981 set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
982 set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */
983 Pico_mcd->regs[0x40>>1].byte.h = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
987 case 0x05: /* Track Start Time (MM:SS:FF) */
989 int track = Pico_mcd->regs[0x46>>1].byte.h * 10 + Pico_mcd->regs[0x46>>1].byte.l;
990 int lba = cdd.toc.tracks[track-1].start + 150;
991 set_reg16(0x38, (cdd.status << 8) | 0x05);
992 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
993 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
994 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
995 Pico_mcd->regs[0x40>>1].byte.h = track % 10; /* Track Number (low digit) */
998 /* RS6 bit 3 is set for the first (DATA) track */
999 Pico_mcd->regs[0x3e>>1].byte.h |= 0x08;
1007 error("Unknown CDD Command %02X (%X)\n", Pico_mcd->regs[0x44>>1].byte.l, s68k.pc);
1015 case 0x03: /* Play */
1017 /* reset track index */
1020 /* new LBA position */
1021 int lba = ((Pico_mcd->regs[0x44>>1].byte.h * 10 + Pico_mcd->regs[0x44>>1].byte.l) * 60 +
1022 (Pico_mcd->regs[0x46>>1].byte.h * 10 + Pico_mcd->regs[0x46>>1].byte.l)) * 75 +
1023 (Pico_mcd->regs[0x48>>1].byte.h * 10 + Pico_mcd->regs[0x48>>1].byte.l) - 150;
1025 /* CD drive latency */
1028 /* Fixes a few games hanging during intro because they expect data to be read with some delay */
1029 /* Radical Rex needs at least one interrupt delay */
1030 /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
1031 /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */
1032 /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */
1036 /* CD drive seek time */
1037 /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
1038 /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
1039 /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
1040 /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
1043 cdd.latency += (((lba - cdd.lba) * 120) / 270000);
1047 cdd.latency += (((cdd.lba - lba) * 120) / 270000);
1050 /* update current LBA */
1053 /* get track index */
1054 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1056 #ifdef USE_LIBTREMOR
1057 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1058 /* check if track index has changed */
1059 if (index != cdd.index)
1061 /* close previous track VORBIS file structure to save memory */
1062 if (cdd.toc.tracks[cdd.index].vf.datasource)
1064 ogg_free(cdd.index);
1067 /* open current track VORBIS file */
1068 if (cdd.toc.tracks[index].vf.seekable)
1070 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1076 /* update current track index */
1079 /* stay within track limits when seeking files */
1080 if (lba < cdd.toc.tracks[index].start)
1082 lba = cdd.toc.tracks[index].start;
1085 /* seek to current block */
1089 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1091 #ifdef USE_LIBTREMOR
1092 else if (cdd.toc.tracks[index].vf.seekable)
1094 /* VORBIS AUDIO track */
1095 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1099 else if (cdd.toc.tracks[index].fd)
1101 /* PCM AUDIO track */
1102 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1107 cdd_change_track(index, lba);
1111 /* no audio track playing (yet) */
1112 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1115 cdd.status = CD_PLAY;
1117 /* return track index in RS2-RS3 */
1118 set_reg16(0x38, (CD_PLAY << 8) | 0x02);
1119 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A);
1120 set_reg16(0x3c, 0x0000);
1121 set_reg16(0x3e, 0x0000);
1122 Pico_mcd->regs[0x40>>1].byte.h = 0x00;
1126 case 0x04: /* Seek */
1128 /* reset track index */
1131 /* new LBA position */
1132 int lba = ((Pico_mcd->regs[0x44>>1].byte.h * 10 + Pico_mcd->regs[0x44>>1].byte.l) * 60 +
1133 (Pico_mcd->regs[0x46>>1].byte.h * 10 + Pico_mcd->regs[0x46>>1].byte.l)) * 75 +
1134 (Pico_mcd->regs[0x48>>1].byte.h * 10 + Pico_mcd->regs[0x48>>1].byte.l) - 150;
1136 /* CD drive seek time */
1137 /* We are using similar linear model as above, although still not exactly accurate, */
1138 /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
1139 /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
1142 cdd.latency = ((lba - cdd.lba) * 120) / 270000;
1146 cdd.latency = ((cdd.lba - lba) * 120) / 270000;
1149 /* update current LBA */
1152 /* get current track index */
1153 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1155 #ifdef USE_LIBTREMOR
1156 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1157 /* check if track index has changed */
1158 if (index != cdd.index)
1160 /* close previous track VORBIS file structure to save memory */
1161 if (cdd.toc.tracks[cdd.index].vf.datasource)
1163 ogg_free(cdd.index);
1166 /* open current track VORBIS file */
1167 if (cdd.toc.tracks[index].vf.seekable)
1169 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1175 /* update current track index */
1178 /* stay within track limits */
1179 if (lba < cdd.toc.tracks[index].start)
1181 lba = cdd.toc.tracks[index].start;
1184 /* seek to current block */
1188 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1190 #ifdef USE_LIBTREMOR
1191 else if (cdd.toc.tracks[index].vf.seekable)
1193 /* VORBIS AUDIO track */
1194 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1198 else if (cdd.toc.tracks[index].fd)
1200 /* PCM AUDIO track */
1201 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1205 /* no audio track playing */
1206 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1209 cdd.status = CD_SEEK;
1211 /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */
1212 set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
1213 set_reg16(0x3a, 0x0000);
1214 set_reg16(0x3c, 0x0000);
1215 set_reg16(0x3e, 0x0000);
1216 set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
1220 case 0x06: /* Pause */
1222 /* no audio track playing */
1223 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1225 /* update status (RS1-RS8 unchanged) */
1226 cdd.status = Pico_mcd->regs[0x38>>1].byte.h = CD_READY;
1230 case 0x07: /* Resume */
1232 /* update status (RS1-RS8 unchanged) */
1233 cdd.status = Pico_mcd->regs[0x38>>1].byte.h = CD_PLAY;
1237 case 0x08: /* Forward Scan */
1239 /* reset scanning direction / speed */
1240 cdd.scanOffset = CD_SCAN_SPEED;
1242 /* update status (RS1-RS8 unchanged) */
1243 cdd.status = Pico_mcd->regs[0x38>>1].byte.h = CD_SCAN;
1247 case 0x09: /* Rewind Scan */
1249 /* reset scanning direction / speed */
1250 cdd.scanOffset = -CD_SCAN_SPEED;
1252 /* update status (RS1-RS8 unchanged) */
1253 cdd.status = Pico_mcd->regs[0x38>>1].byte.h = CD_SCAN;
1258 case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
1260 /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
1261 /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */
1262 /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */
1263 /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
1265 /* no audio track playing */
1266 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1268 /* update status (RS1-RS8 unchanged) */
1269 cdd.status = Pico_mcd->regs[0x38>>1].byte.h = CD_READY;
1273 case 0x0c: /* Close Tray */
1275 /* no audio track playing */
1276 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1279 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
1281 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
1282 set_reg16(0x38, 0x0000);
1283 set_reg16(0x3a, 0x0000);
1284 set_reg16(0x3c, 0x0000);
1285 set_reg16(0x3e, 0x0000);
1286 set_reg16(0x40, 0x000f);
1288 if (PicoMCDcloseTray)
1293 case 0x0d: /* Open Tray */
1295 /* no audio track playing */
1296 Pico_mcd->regs[0x36>>1].byte.h = 0x01;
1298 /* update status (RS1-RS8 ignored) */
1299 cdd.status = CD_OPEN;
1300 set_reg16(0x38, CD_OPEN << 8);
1301 set_reg16(0x3a, 0x0000);
1302 set_reg16(0x3c, 0x0000);
1303 set_reg16(0x3e, 0x0000);
1304 set_reg16(0x40, ~CD_OPEN & 0x0f);
1306 if (PicoMCDopenTray)
1311 default: /* Unknown command */
1313 error("Unknown CDD Command !!!\n");
1315 Pico_mcd->regs[0x38>>1].byte.h = cdd.status;
1319 /* only compute checksum when necessary */
1320 Pico_mcd->regs[0x40>>1].byte.l =
1321 ~(Pico_mcd->regs[0x38>>1].byte.h + Pico_mcd->regs[0x38>>1].byte.l +
1322 Pico_mcd->regs[0x3a>>1].byte.h + Pico_mcd->regs[0x3a>>1].byte.l +
1323 Pico_mcd->regs[0x3c>>1].byte.h + Pico_mcd->regs[0x3c>>1].byte.l +
1324 Pico_mcd->regs[0x3e>>1].byte.h + Pico_mcd->regs[0x3e>>1].byte.l +
1325 Pico_mcd->regs[0x40>>1].byte.h) & 0x0f;
1328 // vim:shiftwidth=2:ts=2:expandtab