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 = 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;
430 /* disc not scanned yet */
431 cdd.status = NO_DISC;
438 int was_loaded = cdd.loaded;
444 /* close CD tracks */
445 if (cdd.toc.tracks[0].fd)
447 pm_close(cdd.toc.tracks[0].fd);
448 cdd.toc.tracks[0].fd = NULL;
451 for (i = 1; i < cdd.toc.last; i++)
454 if (cdd.toc.tracks[i].vf.datasource)
456 /* close VORBIS file (if still opened) */
457 ov_clear(&cdd.toc.tracks[i].vf);
461 if (cdd.toc.tracks[i].fd)
464 if (Pico_mcd->cdda_type == CT_MP3)
465 fclose(cdd.toc.tracks[i].fd);
467 pm_close(cdd.toc.tracks[0].fd);
469 /* detect single file images */
470 if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
481 if (cdd.status != CD_OPEN)
482 cdd.status = NO_DISC;
486 memset(&cdd.toc, 0x00, sizeof(cdd.toc));
488 /* unknown CD image file format */
494 void cdd_read_data(uint8 *dst)
496 /* only read DATA track sectors */
497 if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
500 if (cdd.sectorSize == 2352)
502 /* skip 16-byte header */
503 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
506 /* read sector data (Mode 1 = 2048 bytes) */
507 pm_read(dst, 2048, cdd.toc.tracks[0].fd);
512 void cdd_read_audio(unsigned int samples)
514 /* previous audio outputs */
515 int16 l = cdd.audio[0];
516 int16 r = cdd.audio[1];
518 /* get number of internal clocks (samples) needed */
519 samples = blip_clocks_needed(blip[0], samples);
521 /* audio track playing ? */
522 if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
526 /* current CD-DA fader volume */
527 int curVol = cdd.volume;
529 /* CD-DA fader volume setup (0-1024) */
530 int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
532 /* read samples from current block */
534 if (cdd.toc.tracks[cdd.index].vf.datasource)
537 int16 *ptr = (int16 *) (cdc.ram);
538 samples = samples * 4;
539 while (done < samples)
541 len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
551 /* process 16-bit (host-endian) stereo samples */
552 for (i=0; i<samples; i++)
554 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
555 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
556 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
559 delta = ((ptr[0] * mul) / 1024) - l;
562 blip_add_delta_fast(blip[0], i, delta);
565 delta = ((ptr[0] * mul) / 1024) - r;
568 blip_add_delta_fast(blip[1], i, delta);
570 /* update CD-DA fader volume (one step/sample) */
576 else if (curVol > endVol)
583 /* audio will remain muted until next setup */
592 int16 *ptr = (int16 *) (cdc.ram);
594 uint8 *ptr = cdc.ram;
596 fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
598 /* process 16-bit (little-endian) stereo samples */
599 for (i=0; i<samples; i++)
601 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
602 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
603 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
607 delta = ((ptr[0] * mul) / 1024) - l;
610 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
614 blip_add_delta_fast(blip[0], i, delta);
618 delta = ((ptr[0] * mul) / 1024) - r;
621 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
625 blip_add_delta_fast(blip[1], i, delta);
627 /* update CD-DA fader volume (one step/sample) */
633 else if (curVol > endVol)
640 /* audio will remain muted until next setup */
646 /* save current CD-DA fader volume */
649 /* save last audio output for next frame */
655 /* no audio output */
656 if (l) blip_add_delta_fast(blip[0], 0, -l);
657 if (r) blip_add_delta_fast(blip[1], 0, -r);
659 /* save audio output for next frame */
664 /* end of Blip Buffer timeframe */
665 blip_end_frame(blip[0], samples);
666 blip_end_frame(blip[1], samples);
671 void cdd_update(void)
674 error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
678 if (cdd.status == CD_SEEK)
688 cdd.status = CD_READY;
692 else if (cdd.status == CD_PLAY)
704 /* DATA sector header (CD-ROM Mode 1) */
706 uint32 msf = cdd.lba + 150;
707 header[0] = lut_BCD_8[(msf / 75) / 60];
708 header[1] = lut_BCD_8[(msf / 75) % 60];
709 header[2] = lut_BCD_8[(msf % 75)];
712 /* data track sector read is controlled by CDC */
713 cdd.lba += cdc_decoder_update(header);
715 else if (cdd.index < cdd.toc.last)
717 uint8 header[4] = { 0, };
719 /* check against audio track start index */
720 if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
722 /* audio track playing */
723 Pico_mcd->s68k_regs[0x36+0] = 0x00;
726 /* audio blocks are still sent to CDC as well as CD DAC/Fader */
727 cdc_decoder_update(header);
729 /* next audio block is automatically read */
739 /* check end of current track */
740 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
743 #ifdef DISABLE_MANY_OGG_OPEN_FILES
744 /* close previous track VORBIS file structure to save memory */
745 if (cdd.toc.tracks[cdd.index].vf.datasource)
751 /* play next track */
754 /* PAUSE between tracks */
755 Pico_mcd->s68k_regs[0x36+0] = 0x01;
757 /* seek to next audio track start */
759 if (cdd.toc.tracks[cdd.index].vf.seekable)
761 #ifdef DISABLE_MANY_OGG_OPEN_FILES
762 /* VORBIS file need to be opened first */
763 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
765 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
770 if (cdd.toc.tracks[cdd.index].fd)
772 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
776 cdd_change_track(cdd.index, cdd.lba);
783 else if (cdd.status == CD_SCAN)
785 /* fast-forward or fast-rewind */
786 cdd.lba += cdd.scanOffset;
788 /* check current track limits */
789 if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
792 #ifdef DISABLE_MANY_OGG_OPEN_FILES
793 /* close previous track VORBIS file structure to save memory */
794 if (cdd.toc.tracks[cdd.index].vf.datasource)
803 /* skip directly to track start position */
804 cdd.lba = cdd.toc.tracks[cdd.index].start;
806 /* AUDIO track playing ? */
807 if (cdd.status == CD_PLAY)
809 Pico_mcd->s68k_regs[0x36+0] = 0x00;
812 else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
815 #ifdef DISABLE_MANY_OGG_OPEN_FILES
816 /* close previous track VORBIS file structure to save memory */
817 if (cdd.toc.tracks[cdd.index].vf.datasource)
827 /* skip directly to track end position */
828 cdd.lba = cdd.toc.tracks[cdd.index].end;
831 /* check disc limits */
837 else if (cdd.index >= cdd.toc.last)
839 /* no AUDIO track playing */
840 Pico_mcd->s68k_regs[0x36+0] = 0x01;
843 cdd.index = cdd.toc.last;
844 cdd.lba = cdd.toc.end;
849 /* seek to current block */
852 /* no AUDIO track playing */
853 Pico_mcd->s68k_regs[0x36+0] = 0x01;
856 pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
859 else if (cdd.toc.tracks[cdd.index].vf.seekable)
861 #ifdef DISABLE_MANY_OGG_OPEN_FILES
862 /* check if a new track is being played */
863 if (!cdd.toc.tracks[cdd.index].vf.datasource)
865 /* VORBIS file need to be opened first */
866 ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0);
869 /* VORBIS AUDIO track */
870 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
874 else if (cdd.toc.tracks[cdd.index].fd)
876 /* PCM AUDIO track */
877 fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
882 cdd_change_track(cdd.index, cdd.lba);
888 #define set_reg16(r, v) { \
890 Pico_mcd->s68k_regs[(r)] = _v >> 8; \
891 Pico_mcd->s68k_regs[(r)+1] = _v; \
894 void cdd_process(void)
896 /* Process CDD command */
897 switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f)
899 case 0x00: /* Drive Status */
901 /* RS1-RS8 normally unchanged */
902 Pico_mcd->s68k_regs[0x38+0] = cdd.status;
904 /* unless RS1 indicated invalid track infos */
905 if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
907 /* and SEEK has ended */
908 if (cdd.status != CD_SEEK)
910 /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */
911 Pico_mcd->s68k_regs[0x38+1] = 0x02;
912 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
918 case 0x01: /* Stop Drive */
921 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
923 /* no audio track playing */
924 Pico_mcd->s68k_regs[0x36+0] = 0x01;
926 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
927 set_reg16(0x38, 0x0000);
928 set_reg16(0x3a, 0x0000);
929 set_reg16(0x3c, 0x0000);
930 set_reg16(0x3e, 0x0000);
931 set_reg16(0x40, 0x000f);
935 case 0x02: /* Read TOC */
937 if (cdd.status == NO_DISC)
938 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
940 /* Infos automatically retrieved by CDD processor from Q-Channel */
941 /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */
942 switch (Pico_mcd->s68k_regs[0x44+1])
944 case 0x00: /* Current Absolute Time (MM:SS:FF) */
946 int lba = cdd.lba + 150;
947 set_reg16(0x38, cdd.status << 8);
948 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
949 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
950 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
951 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) */
955 case 0x01: /* Current Track Relative Time (MM:SS:FF) */
957 int lba = cdd.lba - cdd.toc.tracks[cdd.index].start;
958 set_reg16(0x38, (cdd.status << 8) | 0x01);
959 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
960 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
961 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
962 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) */
966 case 0x02: /* Current Track Number */
968 set_reg16(0x38, (cdd.status << 8) | 0x02);
969 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A);
970 set_reg16(0x3c, 0x0000);
971 set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */
972 Pico_mcd->s68k_regs[0x40+0] = 0x00;
976 case 0x03: /* Total length (MM:SS:FF) */
978 int lba = cdd.toc.end + 150;
979 set_reg16(0x38, (cdd.status << 8) | 0x03);
980 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
981 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
982 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
983 Pico_mcd->s68k_regs[0x40+0] = 0x00;
987 case 0x04: /* First & Last Track Numbers */
989 set_reg16(0x38, (cdd.status << 8) | 0x04);
990 set_reg16(0x3a, 0x0001);
991 set_reg16(0x3c, lut_BCD_16[cdd.toc.last]);
992 set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */
993 Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */
997 case 0x05: /* Track Start Time (MM:SS:FF) */
999 int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1];
1000 int lba = cdd.toc.tracks[track-1].start + 150;
1001 set_reg16(0x38, (cdd.status << 8) | 0x05);
1002 set_reg16(0x3a, lut_BCD_16[(lba/75)/60]);
1003 set_reg16(0x3c, lut_BCD_16[(lba/75)%60]);
1004 set_reg16(0x3e, lut_BCD_16[(lba%75)]);
1005 Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */
1008 /* RS6 bit 3 is set for the first (DATA) track */
1009 Pico_mcd->s68k_regs[0x3e + 0] |= 0x08;
1017 error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc);
1025 case 0x03: /* Play */
1027 /* reset track index */
1030 /* new LBA position */
1031 int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
1032 (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
1033 (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
1035 /* CD drive latency */
1038 /* Fixes a few games hanging during intro because they expect data to be read with some delay */
1039 /* Radical Rex needs at least one interrupt delay */
1040 /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */
1041 /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */
1042 /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */
1046 /* CD drive seek time */
1047 /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
1048 /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
1049 /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
1050 /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
1053 cdd.latency += (((lba - cdd.lba) * 120) / 270000);
1057 cdd.latency += (((cdd.lba - lba) * 120) / 270000);
1060 /* update current LBA */
1063 /* get track index */
1064 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1066 #ifdef USE_LIBTREMOR
1067 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1068 /* check if track index has changed */
1069 if (index != cdd.index)
1071 /* close previous track VORBIS file structure to save memory */
1072 if (cdd.toc.tracks[cdd.index].vf.datasource)
1074 ogg_free(cdd.index);
1077 /* open current track VORBIS file */
1078 if (cdd.toc.tracks[index].vf.seekable)
1080 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1086 /* update current track index */
1089 /* stay within track limits when seeking files */
1090 if (lba < cdd.toc.tracks[index].start)
1092 lba = cdd.toc.tracks[index].start;
1095 /* seek to current block */
1099 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1101 #ifdef USE_LIBTREMOR
1102 else if (cdd.toc.tracks[index].vf.seekable)
1104 /* VORBIS AUDIO track */
1105 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1109 else if (cdd.toc.tracks[index].fd)
1111 /* PCM AUDIO track */
1112 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1117 cdd_change_track(index, lba);
1121 /* no audio track playing (yet) */
1122 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1125 cdd.status = CD_PLAY;
1127 /* return track index in RS2-RS3 */
1128 set_reg16(0x38, (CD_PLAY << 8) | 0x02);
1129 set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A);
1130 set_reg16(0x3c, 0x0000);
1131 set_reg16(0x3e, 0x0000);
1132 Pico_mcd->s68k_regs[0x40+0] = 0x00;
1136 case 0x04: /* Seek */
1138 /* reset track index */
1141 /* new LBA position */
1142 int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 +
1143 (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
1144 (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
1146 /* CD drive seek time */
1147 /* We are using similar linear model as above, although still not exactly accurate, */
1148 /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
1149 /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
1152 cdd.latency = ((lba - cdd.lba) * 120) / 270000;
1156 cdd.latency = ((cdd.lba - lba) * 120) / 270000;
1159 /* update current LBA */
1162 /* get current track index */
1163 while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1165 #ifdef USE_LIBTREMOR
1166 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1167 /* check if track index has changed */
1168 if (index != cdd.index)
1170 /* close previous track VORBIS file structure to save memory */
1171 if (cdd.toc.tracks[cdd.index].vf.datasource)
1173 ogg_free(cdd.index);
1176 /* open current track VORBIS file */
1177 if (cdd.toc.tracks[index].vf.seekable)
1179 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1185 /* update current track index */
1188 /* stay within track limits */
1189 if (lba < cdd.toc.tracks[index].start)
1191 lba = cdd.toc.tracks[index].start;
1194 /* seek to current block */
1198 pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1200 #ifdef USE_LIBTREMOR
1201 else if (cdd.toc.tracks[index].vf.seekable)
1203 /* VORBIS AUDIO track */
1204 ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset);
1208 else if (cdd.toc.tracks[index].fd)
1210 /* PCM AUDIO track */
1211 fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1215 /* no audio track playing */
1216 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1219 cdd.status = CD_SEEK;
1221 /* 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) */
1222 set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
1223 set_reg16(0x3a, 0x0000);
1224 set_reg16(0x3c, 0x0000);
1225 set_reg16(0x3e, 0x0000);
1226 set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
1230 case 0x06: /* Pause */
1232 /* no audio track playing */
1233 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1235 /* update status (RS1-RS8 unchanged) */
1236 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1240 case 0x07: /* Resume */
1242 /* update status (RS1-RS8 unchanged) */
1243 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY;
1247 case 0x08: /* Forward Scan */
1249 /* reset scanning direction / speed */
1250 cdd.scanOffset = CD_SCAN_SPEED;
1252 /* update status (RS1-RS8 unchanged) */
1253 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1257 case 0x09: /* Rewind Scan */
1259 /* reset scanning direction / speed */
1260 cdd.scanOffset = -CD_SCAN_SPEED;
1262 /* update status (RS1-RS8 unchanged) */
1263 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1268 case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
1270 /* TC3 corresponds to seek direction (00=forward, FF=reverse) */
1271 /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */
1272 /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */
1273 /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */
1275 /* no audio track playing */
1276 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1278 /* update status (RS1-RS8 unchanged) */
1279 cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1283 case 0x0c: /* Close Tray */
1285 /* no audio track playing */
1286 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1289 cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
1291 /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */
1292 set_reg16(0x38, 0x0000);
1293 set_reg16(0x3a, 0x0000);
1294 set_reg16(0x3c, 0x0000);
1295 set_reg16(0x3e, 0x0000);
1296 set_reg16(0x40, 0x000f);
1298 if (PicoMCDcloseTray)
1304 case 0x0d: /* Open Tray */
1306 /* no audio track playing */
1307 Pico_mcd->s68k_regs[0x36+0] = 0x01;
1309 /* update status (RS1-RS8 ignored) */
1310 cdd.status = CD_OPEN;
1311 set_reg16(0x38, CD_OPEN << 8);
1312 set_reg16(0x3a, 0x0000);
1313 set_reg16(0x3c, 0x0000);
1314 set_reg16(0x3e, 0x0000);
1315 set_reg16(0x40, ~CD_OPEN & 0x0f);
1317 if (PicoMCDopenTray)
1322 default: /* Unknown command */
1324 error("Unknown CDD Command !!!\n");
1326 Pico_mcd->s68k_regs[0x38+0] = cdd.status;
1330 /* only compute checksum when necessary */
1331 Pico_mcd->s68k_regs[0x40 + 1] =
1332 ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] +
1333 Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] +
1334 Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] +
1335 Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] +
1336 Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f;
1339 // vim:shiftwidth=2:ts=2:expandtab