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
126 /* supported WAVE file header (16-bit stereo samples @44.1kHz) */
127 static const unsigned char waveHeader[32] =
129 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
130 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61
135 #ifdef DISABLE_MANY_OGG_OPEN_FILES
136 static void ogg_free(int i)
138 /* clear OGG file descriptor to prevent file from being closed */
139 cdd.toc.tracks[i].vf.datasource = NULL;
141 /* close VORBIS file structure */
142 ov_clear(&cdd.toc.tracks[i].vf);
144 /* indicates that the track is a seekable VORBIS file */
145 cdd.toc.tracks[i].vf.seekable = 1;
147 /* reset file reading position */
148 fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET);
155 /* reset cycle counter */
158 /* reset drive access latency */
161 /* reset track index */
164 /* reset logical block address */
168 cdd.status = NO_DISC;
170 /* reset CD-DA fader (full volume) */
173 /* clear CD-DA output */
174 cdd.audio[0] = cdd.audio[1] = 0;
177 /* FIXME: use cdd_read_audio() instead */
178 static void cdd_change_track(int index, int lba)
180 int i, base, lba_offset, lb_len;
182 for (i = index; i > 0; i--)
183 if (cdd.toc.tracks[i].fd != NULL)
186 Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd;
187 base = cdd.toc.tracks[index].offset;
188 lba_offset = lba - cdd.toc.tracks[index].start;
189 lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start;
191 elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base);
193 cdda_start_play(base, lba_offset, lb_len);
196 int cdd_context_save(uint8 *state)
200 save_param(&cdd.cycles, sizeof(cdd.cycles));
201 save_param(&cdd.latency, sizeof(cdd.latency));
202 save_param(&cdd.index, sizeof(cdd.index));
203 save_param(&cdd.lba, sizeof(cdd.lba));
204 save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
205 save_param(&cdd.volume, sizeof(cdd.volume));
206 save_param(&cdd.status, sizeof(cdd.status));
211 int cdd_context_load(uint8 *state)
217 #ifdef DISABLE_MANY_OGG_OPEN_FILES
218 /* close previous track VORBIS file structure to save memory */
219 if (cdd.toc.tracks[cdd.index].vf.datasource)
226 load_param(&cdd.cycles, sizeof(cdd.cycles));
227 load_param(&cdd.latency, sizeof(cdd.latency));
228 load_param(&cdd.index, sizeof(cdd.index));
229 load_param(&cdd.lba, sizeof(cdd.lba));
230 load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
231 load_param(&cdd.volume, sizeof(cdd.volume));
232 load_param(&cdd.status, sizeof(cdd.status));
234 /* adjust current LBA within track limit */
236 if (lba < cdd.toc.tracks[cdd.index].start)
238 lba = cdd.toc.tracks[cdd.index].start;
241 /* seek to current track position */
245 if (cdd.toc.tracks[0].fd)
247 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
251 else if (cdd.toc.tracks[cdd.index].vf.seekable)
253 #ifdef DISABLE_MANY_OGG_OPEN_FILES
254 /* VORBIS file need to be opened first */
255 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
257 /* VORBIS AUDIO track */
258 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
262 else if (cdd.toc.tracks[cdd.index].fd)
264 /* PCM AUDIO track */
265 fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
270 cdd_change_track(cdd.index, lba);
277 int cdd_context_load_old(uint8 *state)
279 memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
283 int cdd_load(const char *filename, int type)
288 /* first unmount any loaded disc */
291 /* genplus parses cue here, in PD we use our own parser */
292 ret = load_cd_image(filename, &type);
296 /* read first 16 bytes */
297 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
299 /* look for valid CD image ID string */
300 if (memcmp("SEGADISCSYSTEM", header, 14))
302 /* if not found, read next 16 bytes */
303 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
305 /* look again for valid CD image ID string */
306 if (memcmp("SEGADISCSYSTEM", header, 14))
308 elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
309 /* assume bin without security code */
312 /* BIN format (2352 bytes data blocks) */
313 cdd.sectorSize = 2352;
317 /* ISO format (2048 bytes data blocks) */
318 cdd.sectorSize = 2048;
321 ret = (type == CT_BIN) ? 2352 : 2048;
322 if (ret != cdd.sectorSize)
323 elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
325 /* read CD image header + security code */
326 pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
328 /* Simulate audio tracks if none found */
329 if (cdd.toc.last == 1)
331 /* Some games require exact TOC infos */
332 if (strstr(header + 0x180,"T-95035") != NULL)
335 cdd.toc.last = cdd.toc.end = 0;
338 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
339 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
340 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
343 while (cdd.toc.last < 21);
345 else if (strstr(header + 0x180,"T-127015") != NULL)
347 /* Lunar - The Silver Star */
348 cdd.toc.last = cdd.toc.end = 0;
351 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
352 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
353 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
356 while (cdd.toc.last < 52);
358 else if (strstr(header + 0x180,"T-113045") != NULL)
360 /* Shadow of the Beast II */
361 cdd.toc.last = cdd.toc.end = 0;
364 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
365 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
366 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
369 while (cdd.toc.last < 15);
371 else if (strstr(header + 0x180,"T-143025") != NULL)
373 /* Dungeon Explorer */
374 cdd.toc.last = cdd.toc.end = 0;
377 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
378 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
379 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
382 while (cdd.toc.last < 13);
384 else if (strstr(header + 0x180,"MK-4410") != NULL)
386 /* Final Fight CD (USA, Europe) */
387 cdd.toc.last = cdd.toc.end = 0;
390 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
391 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
392 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
395 while (cdd.toc.last < 26);
397 else if (strstr(header + 0x180,"G-6013") != NULL)
399 /* Final Fight CD (Japan) */
400 cdd.toc.last = cdd.toc.end = 0;
403 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
404 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
405 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
408 while (cdd.toc.last < 29);
413 /* default TOC (99 tracks & 2s per audio tracks) */
416 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
417 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
418 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
421 while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
427 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
432 /* disc not scanned yet */
433 cdd.status = NO_DISC;
440 int was_loaded = cdd.loaded;
446 /* close CD tracks */
447 if (cdd.toc.tracks[0].fd)
449 pm_close(cdd.toc.tracks[0].fd);
450 cdd.toc.tracks[0].fd = NULL;
453 for (i = 1; i < cdd.toc.last; i++)
456 if (cdd.toc.tracks[i].vf.datasource)
458 /* close VORBIS file (if still opened) */
459 ov_clear(&cdd.toc.tracks[i].vf);
463 if (cdd.toc.tracks[i].fd)
466 if (Pico_mcd->cdda_type == CT_MP3)
467 fclose(cdd.toc.tracks[i].fd);
469 pm_close(cdd.toc.tracks[0].fd);
471 /* detect single file images */
472 if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
483 if (cdd.status != CD_OPEN)
484 cdd.status = NO_DISC;
488 memset(&cdd.toc, 0x00, sizeof(cdd.toc));
490 /* unknown CD image file format */
496 void cdd_read_data(uint8 *dst)
498 /* only read DATA track sectors */
499 if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
502 if (cdd.sectorSize == 2352)
504 /* skip 16-byte header */
505 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
508 /* read sector data (Mode 1 = 2048 bytes) */
509 pm_read(dst, 2048, cdd.toc.tracks[0].fd);
514 void cdd_read_audio(unsigned int samples)
516 /* previous audio outputs */
517 int16 l = cdd.audio[0];
518 int16 r = cdd.audio[1];
520 /* get number of internal clocks (samples) needed */
521 samples = blip_clocks_needed(blip[0], samples);
523 /* audio track playing ? */
524 if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
528 /* current CD-DA fader volume */
529 int curVol = cdd.volume;
531 /* CD-DA fader volume setup (0-1024) */
532 int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
534 /* read samples from current block */
536 if (cdd.toc.tracks[cdd.index].vf.datasource)
539 int16 *ptr = (int16 *) (cdc.ram);
540 samples = samples * 4;
541 while (done < samples)
543 len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
553 /* process 16-bit (host-endian) stereo samples */
554 for (i=0; i<samples; i++)
556 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
557 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
558 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
561 delta = ((ptr[0] * mul) / 1024) - l;
564 blip_add_delta_fast(blip[0], i, delta);
567 delta = ((ptr[0] * mul) / 1024) - r;
570 blip_add_delta_fast(blip[1], i, delta);
572 /* update CD-DA fader volume (one step/sample) */
578 else if (curVol > endVol)
585 /* audio will remain muted until next setup */
594 int16 *ptr = (int16 *) (cdc.ram);
596 uint8 *ptr = cdc.ram;
598 fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
600 /* process 16-bit (little-endian) stereo samples */
601 for (i=0; i<samples; i++)
603 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
604 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
605 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
609 delta = ((ptr[0] * mul) / 1024) - l;
612 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
616 blip_add_delta_fast(blip[0], i, delta);
620 delta = ((ptr[0] * mul) / 1024) - r;
623 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
627 blip_add_delta_fast(blip[1], i, delta);
629 /* update CD-DA fader volume (one step/sample) */
635 else if (curVol > endVol)
642 /* audio will remain muted until next setup */
648 /* save current CD-DA fader volume */
651 /* save last audio output for next frame */
657 /* no audio output */
658 if (l) blip_add_delta_fast(blip[0], 0, -l);
659 if (r) blip_add_delta_fast(blip[1], 0, -r);
661 /* save audio output for next frame */
666 /* end of Blip Buffer timeframe */
667 blip_end_frame(blip[0], samples);
668 blip_end_frame(blip[1], samples);
673 void cdd_update(void)
676 error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
680 if (cdd.status == CD_SEEK)
690 cdd.status = CD_READY;
694 else if (cdd.status == CD_PLAY)
706 /* DATA sector header (CD-ROM Mode 1) */
708 uint32 msf = cdd.lba + 150;
709 header[0] = lut_BCD_8[(msf / 75) / 60];
710 header[1] = lut_BCD_8[(msf / 75) % 60];
711 header[2] = lut_BCD_8[(msf % 75)];
714 /* data track sector read is controlled by CDC */
715 cdd.lba += cdc_decoder_update(header);
717 else if (cdd.index < cdd.toc.last)
719 uint8 header[4] = { 0, };
721 /* check against audio track start index */
722 if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
724 /* audio track playing */
725 Pico_mcd->s68k_regs[0x36+0] = 0x00;
728 /* audio blocks are still sent to CDC as well as CD DAC/Fader */
729 cdc_decoder_update(header);
731 /* next audio block is automatically read */
741 /* check end of current track */
742 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
745 #ifdef DISABLE_MANY_OGG_OPEN_FILES
746 /* close previous track VORBIS file structure to save memory */
747 if (cdd.toc.tracks[cdd.index].vf.datasource)
753 /* play next track */
756 /* PAUSE between tracks */
757 Pico_mcd->s68k_regs[0x36+0] = 0x01;
759 /* seek to next audio track start */
761 if (cdd.toc.tracks[cdd.index].vf.seekable)
763 #ifdef DISABLE_MANY_OGG_OPEN_FILES
764 /* VORBIS file need to be opened first */
765 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
767 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
772 if (cdd.toc.tracks[cdd.index].fd)
774 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
778 cdd_change_track(cdd.index, cdd.lba);
785 else if (cdd.status == CD_SCAN)
787 /* fast-forward or fast-rewind */
788 cdd.lba += cdd.scanOffset;
790 /* check current track limits */
791 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
794 #ifdef DISABLE_MANY_OGG_OPEN_FILES
795 /* close previous track VORBIS file structure to save memory */
796 if (cdd.toc.tracks[cdd.index].vf.datasource)
805 /* skip directly to track start position */
806 cdd.lba = cdd.toc.tracks[cdd.index].start;
808 /* AUDIO track playing ? */
809 if (cdd.status == CD_PLAY)
811 Pico_mcd->s68k_regs[0x36+0] = 0x00;
814 else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
817 #ifdef DISABLE_MANY_OGG_OPEN_FILES
818 /* close previous track VORBIS file structure to save memory */
819 if (cdd.toc.tracks[cdd.index].vf.datasource)
829 /* skip directly to track end position */
830 cdd.lba = cdd.toc.tracks[cdd.index].end;
833 /* check disc limits */
839 else if (cdd.index >= cdd.toc.last)
841 /* no AUDIO track playing */
842 Pico_mcd->s68k_regs[0x36+0] = 0x01;
845 cdd.index = cdd.toc.last;
846 cdd.lba = cdd.toc.end;
851 /* seek to current block */
854 /* no AUDIO track playing */
855 Pico_mcd->s68k_regs[0x36+0] = 0x01;
858 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
861 else if (cdd.toc.tracks[cdd.index].vf.seekable)
863 #ifdef DISABLE_MANY_OGG_OPEN_FILES
864 /* check if a new track is being played */
865 if (!cdd.toc.tracks[cdd.index].vf.datasource)
867 /* VORBIS file need to be opened first */
868 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
871 /* VORBIS AUDIO track */
872 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
876 else if (cdd.toc.tracks[cdd.index].fd)
878 /* PCM AUDIO track */
879 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
884 cdd_change_track(cdd.index, cdd.lba);
890 #define set_reg16(r, v) { \
892 Pico_mcd->s68k_regs[(r)] = _v >> 8; \
893 Pico_mcd->s68k_regs[(r)+1] = _v; \
896 void cdd_process(void)
898 /* Process CDD command */
899 switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f)
901 case 0x00: /* Drive Status */
903 /* RS1-RS8 normally unchanged */
904 Pico_mcd->s68k_regs[0x38+0] = cdd.status;
906 /* unless RS1 indicated invalid track infos */
907 if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
909 /* and SEEK has ended */
910 if (cdd.status != CD_SEEK)
912 /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */
913 Pico_mcd->s68k_regs[0x38+1] = 0x02;
914 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
920 case 0x01: /* Stop Drive */
923 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
925 /* no audio track playing */
926 Pico_mcd->s68k_regs[0x36+0] = 0x01;
928 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
929 set_reg16(0x38, 0x0000);
930 set_reg16(0x3a, 0x0000);
931 set_reg16(0x3c, 0x0000);
932 set_reg16(0x3e, 0x0000);
933 set_reg16(0x40, 0x000f);
937 case 0x02: /* Read TOC */
939 if (cdd.status == NO_DISC)
940 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
942 /* Infos automatically retrieved by CDD processor from Q-Channel */
943 /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
944 switch (Pico_mcd->s68k_regs[0x44+1])
946 case 0x00: /* Current Absolute Time (MM:SS:FF) */
948 int lba = cdd.lba + 150;
949 set_reg16(0x38, cdd.status << 8);
950 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
951 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
952 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
953 Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
957 case 0x01: /* Current Track Relative Time (MM:SS:FF) */
959 int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
960 set_reg16(0x38, (cdd.status << 8) | 0x01);
961 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
962 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
963 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
964 Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
968 case 0x02: /* Current Track Number */
970 set_reg16(0x38, (cdd.status << 8) | 0x02);
971 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
972 set_reg16(0x3c, 0x0000);
973 set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
974 Pico_mcd->s68k_regs[0x40+0] = 0x00;
978 case 0x03: /* Total length (MM:SS:FF) */
980 int lba = cdd.toc.end + 150;
981 set_reg16(0x38, (cdd.status << 8) | 0x03);
982 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
983 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
984 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
985 Pico_mcd->s68k_regs[0x40+0] = 0x00;
989 case 0x04: /* First & Last Track Numbers */
991 set_reg16(0x38, (cdd.status << 8) | 0x04);
992 set_reg16(0x3a, 0x0001);
993 set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
994 set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */
995 Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
999 case 0x05: /* Track Start Time (MM:SS:FF) */
1001 int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1];
1002 int lba = cdd.toc.tracks[track-1].start + 150;
1003 set_reg16(0x38, (cdd.status << 8) | 0x05);
1004 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
1005 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
1006 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
1007 Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */
1010 /* RS6 bit 3 is set for the first (DATA) track */
1011 Pico_mcd->s68k_regs[0x3e + 0] |= 0x08;
1019 error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc);
1027 case 0x03: /* Play */
1029 /* reset track index */
1032 /* new LBA position */
1033 int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
1034 (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
1035 (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
1037 /* CD drive latency */
1040 /* Fixes a few games hanging during intro because they expect data to be read with some delay */
1041 /* Radical Rex needs at least one interrupt delay */
1042 /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
1043 /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */
1044 /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */
1048 /* CD drive seek time */
1049 /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
1050 /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
1051 /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
1052 /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
1055 cdd.latency += (((lba - cdd.lba) * 120) / 270000);
1059 cdd.latency += (((cdd.lba - lba) * 120) / 270000);
1062 /* update current LBA */
1065 /* get track index */
1066 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1068 #ifdef USE_LIBTREMOR
1069 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1070 /* check if track index has changed */
1071 if (index != cdd.index)
1073 /* close previous track VORBIS file structure to save memory */
1074 if (cdd.toc.tracks[cdd.index].vf.datasource)
1076 ogg_free(cdd.index);
1079 /* open current track VORBIS file */
1080 if (cdd.toc.tracks[index].vf.seekable)
1082 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1088 /* update current track index */
1091 /* stay within track limits when seeking files */
1092 if (lba < cdd.toc.tracks[index].start)
1094 lba = cdd.toc.tracks[index].start;
1097 /* seek to current block */
1101 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1103 #ifdef USE_LIBTREMOR
1104 else if (cdd.toc.tracks[index].vf.seekable)
1106 /* VORBIS AUDIO track */
1107 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1111 else if (cdd.toc.tracks[index].fd)
1113 /* PCM AUDIO track */
1114 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1119 cdd_change_track(index, lba);
1123 /* no audio track playing (yet) */
1124 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1127 cdd.status = CD_PLAY;
1129 /* return track index in RS2-RS3 */
1130 set_reg16(0x38, (CD_PLAY << 8) | 0x02);
1131 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A);
1132 set_reg16(0x3c, 0x0000);
1133 set_reg16(0x3e, 0x0000);
1134 Pico_mcd->s68k_regs[0x40+0] = 0x00;
1138 case 0x04: /* Seek */
1140 /* reset track index */
1143 /* new LBA position */
1144 int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
1145 (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
1146 (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
1148 /* CD drive seek time */
1149 /* We are using similar linear model as above, although still not exactly accurate, */
1150 /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
1151 /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
1154 cdd.latency = ((lba - cdd.lba) * 120) / 270000;
1158 cdd.latency = ((cdd.lba - lba) * 120) / 270000;
1161 /* update current LBA */
1164 /* get current track index */
1165 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1167 #ifdef USE_LIBTREMOR
1168 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1169 /* check if track index has changed */
1170 if (index != cdd.index)
1172 /* close previous track VORBIS file structure to save memory */
1173 if (cdd.toc.tracks[cdd.index].vf.datasource)
1175 ogg_free(cdd.index);
1178 /* open current track VORBIS file */
1179 if (cdd.toc.tracks[index].vf.seekable)
1181 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1187 /* update current track index */
1190 /* stay within track limits */
1191 if (lba < cdd.toc.tracks[index].start)
1193 lba = cdd.toc.tracks[index].start;
1196 /* seek to current block */
1200 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1202 #ifdef USE_LIBTREMOR
1203 else if (cdd.toc.tracks[index].vf.seekable)
1205 /* VORBIS AUDIO track */
1206 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1210 else if (cdd.toc.tracks[index].fd)
1212 /* PCM AUDIO track */
1213 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1217 /* no audio track playing */
1218 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1221 cdd.status = CD_SEEK;
1223 /* 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) */
1224 set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
1225 set_reg16(0x3a, 0x0000);
1226 set_reg16(0x3c, 0x0000);
1227 set_reg16(0x3e, 0x0000);
1228 set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
1232 case 0x06: /* Pause */
1234 /* no audio track playing */
1235 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1237 /* update status (RS1-RS8 unchanged) */
1238 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1242 case 0x07: /* Resume */
1244 /* update status (RS1-RS8 unchanged) */
1245 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY;
1249 case 0x08: /* Forward Scan */
1251 /* reset scanning direction / speed */
1252 cdd.scanOffset = CD_SCAN_SPEED;
1254 /* update status (RS1-RS8 unchanged) */
1255 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1259 case 0x09: /* Rewind Scan */
1261 /* reset scanning direction / speed */
1262 cdd.scanOffset = -CD_SCAN_SPEED;
1264 /* update status (RS1-RS8 unchanged) */
1265 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1270 case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
1272 /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
1273 /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */
1274 /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */
1275 /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
1277 /* no audio track playing */
1278 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1280 /* update status (RS1-RS8 unchanged) */
1281 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1285 case 0x0c: /* Close Tray */
1287 /* no audio track playing */
1288 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1291 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
1293 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
1294 set_reg16(0x38, 0x0000);
1295 set_reg16(0x3a, 0x0000);
1296 set_reg16(0x3c, 0x0000);
1297 set_reg16(0x3e, 0x0000);
1298 set_reg16(0x40, 0x000f);
1300 if (PicoIn.mcdTrayClose)
1301 PicoIn.mcdTrayClose();
1306 case 0x0d: /* Open Tray */
1308 /* no audio track playing */
1309 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1311 /* update status (RS1-RS8 ignored) */
1312 cdd.status = CD_OPEN;
1313 set_reg16(0x38, CD_OPEN << 8);
1314 set_reg16(0x3a, 0x0000);
1315 set_reg16(0x3c, 0x0000);
1316 set_reg16(0x3e, 0x0000);
1317 set_reg16(0x40, ~CD_OPEN & 0x0f);
1319 if (PicoIn.mcdTrayOpen)
1320 PicoIn.mcdTrayOpen();
1324 default: /* Unknown command */
1326 error("Unknown CDD Command !!!\n");
1328 Pico_mcd->s68k_regs[0x38+0] = cdd.status;
1332 /* only compute checksum when necessary */
1333 Pico_mcd->s68k_regs[0x40 + 1] =
1334 ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] +
1335 Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] +
1336 Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] +
1337 Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] +
1338 Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f;
1341 // vim:shiftwidth=2:ts=2:expandtab