fix clang build
[picodrive.git] / pico / cd / cdd.c
1 /***************************************************************************************
2  *  Genesis Plus
3  *  CD drive processor & CD-DA fader
4  *
5  *  Copyright (C) 2012-2013  Eke-Eke (Genesis Plus GX)
6  *
7  *  Redistribution and use of this code or any derivative works are permitted
8  *  provided that the following conditions are met:
9  *
10  *   - Redistributions may not be sold, nor may they be used in a commercial
11  *     product or activity.
12  *
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.
20  *
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.
24  *
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.
36  *
37  ****************************************************************************************/
38
39 #include "../pico_int.h"
40 #include "genplus_macros.h"
41 #include "cue.h"
42 #include "cdd.h"
43
44 #ifdef USE_LIBTREMOR
45 #define SUPPORTED_EXT 20
46 #else
47 #define SUPPORTED_EXT 10
48 #endif
49
50 cdd_t cdd;
51
52 /* BCD conversion lookup tables */
53 static const uint8 lut_BCD_8[100] =
54 {
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, 
65 };
66
67 static const uint16 lut_BCD_16[100] =
68 {
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, 
79 };
80
81 /* pre-build TOC */
82 static const uint16 toc_snatcher[21] =
83 {
84   56014,   495, 10120, 20555, 1580, 5417, 12502, 16090,  6553, 9681,
85    8148, 20228,  8622,  6142, 5858, 1287,  7424,  3535, 31697, 2485,
86   31380
87 };
88
89 static const uint16 toc_lunar[52] =
90 {
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,
96   685, 3167
97 };
98
99 static const uint32 toc_shadow[15] =
100 {
101   10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792,
102   11637,  2547,  2521,  3856, 900
103 };
104
105 static const uint32 toc_dungeon[13] =
106 {
107   2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
108   3325,  6825, 25275
109 };
110
111 static const uint32 toc_ffight[26] =
112 {
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
116 };
117
118 static const uint32 toc_ffightj[29] =
119 {
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
123 };
124
125 #if 0
126 /* supported WAVE file header (16-bit stereo samples @44.1kHz) */
127 static const unsigned char waveHeader[32] =
128 {
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
131 };
132 #endif
133
134 #ifdef USE_LIBTREMOR
135 #ifdef DISABLE_MANY_OGG_OPEN_FILES
136 static void ogg_free(int i)
137 {
138   /* clear OGG file descriptor to prevent file from being closed */
139   cdd.toc.tracks[i].vf.datasource = NULL;
140
141   /* close VORBIS file structure */
142   ov_clear(&cdd.toc.tracks[i].vf);
143
144   /* indicates that the track is a seekable VORBIS file */
145   cdd.toc.tracks[i].vf.seekable = 1;
146
147   /* reset file reading position */
148   fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET);
149 }
150 #endif
151 #endif
152
153 void cdd_reset(void)
154 {
155   /* reset cycle counter */
156   cdd.cycles = 0;
157   
158   /* reset drive access latency */
159   cdd.latency = 0;
160   
161   /* reset track index */
162   cdd.index = 0;
163   
164   /* reset logical block address */
165   cdd.lba = 0;
166
167   /* reset status */
168   cdd.status = NO_DISC;
169
170   /* reset CD-DA fader (full volume) */
171   cdd.volume = 0x400;
172
173   /* clear CD-DA output */
174   cdd.audio[0] = cdd.audio[1] = 0;
175 }
176
177 /* FIXME: use cdd_read_audio() instead */
178 static void cdd_change_track(int index, int lba)
179 {
180   int i, base, lba_offset, lb_len;
181
182   for (i = index; i > 0; i--)
183     if (cdd.toc.tracks[i].fd != NULL)
184       break;
185
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;
190
191   elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base);
192
193   cdda_start_play(base, lba_offset, lb_len);
194 }
195
196 int cdd_context_save(uint8 *state)
197 {
198   int bufferptr = 0;
199
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));
207
208   return bufferptr;
209 }
210
211 int cdd_context_load(uint8 *state)
212 {
213   int lba;
214   int bufferptr = 0;
215
216 #ifdef USE_LIBTREMOR
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)
220   {
221     ogg_free(cdd.index);
222   }
223 #endif
224 #endif
225
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));
233
234   /* adjust current LBA within track limit */
235   lba = cdd.lba;
236   if (lba < cdd.toc.tracks[cdd.index].start)
237   {
238     lba = cdd.toc.tracks[cdd.index].start;
239   }
240
241   /* seek to current track position */
242   if (!cdd.index)
243   {
244     /* DATA track */
245     if (cdd.toc.tracks[0].fd)
246     {
247       pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
248     }
249   }
250 #ifdef USE_LIBTREMOR
251   else if (cdd.toc.tracks[cdd.index].vf.seekable)
252   {
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);
256 #endif
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);
259   }
260 #endif
261 #if 0
262   else if (cdd.toc.tracks[cdd.index].fd)
263   {
264     /* PCM AUDIO track */
265     fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
266   }
267 #else
268   else
269   {
270     cdd_change_track(cdd.index, lba);
271   }
272 #endif
273
274   return bufferptr;
275 }
276
277 int cdd_context_load_old(uint8 *state)
278 {
279   memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
280   return 12 * 4;
281 }
282
283 int cdd_load(const char *filename, int type)
284 {
285   char header[0x210];
286   int ret;
287
288   /* first unmount any loaded disc */
289   cdd_unload();
290
291   /* genplus parses cue here, in PD we use our own parser */
292   ret = load_cd_image(filename, &type);
293   if (ret != 0)
294     return ret;
295
296   /* read first 16 bytes */
297   pm_read(header, 0x10, cdd.toc.tracks[0].fd);
298
299   /* look for valid CD image ID string */
300   if (memcmp("SEGADISCSYSTEM", header, 14))
301   {    
302     /* if not found, read next 16 bytes */
303     pm_read(header, 0x10, cdd.toc.tracks[0].fd);
304
305     /* look again for valid CD image ID string */
306     if (memcmp("SEGADISCSYSTEM", header, 14))
307     {
308       elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
309       /* assume bin without security code */
310     }
311
312     /* BIN format (2352 bytes data blocks) */
313     cdd.sectorSize = 2352;
314   }
315   else
316   {
317     /* ISO format (2048 bytes data blocks) */
318     cdd.sectorSize = 2048;
319   }
320
321   ret = (type == CT_BIN) ? 2352 : 2048;
322   if (ret != cdd.sectorSize)
323     elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch");
324
325   /* read CD image header + security code */
326   pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
327
328   /* Simulate audio tracks if none found */
329   if (cdd.toc.last == 1)
330   {
331     /* Some games require exact TOC infos */
332     if (strstr(header + 0x180,"T-95035") != NULL)
333     {
334       /* Snatcher */
335       cdd.toc.last = cdd.toc.end = 0;
336       do
337       {
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;
341         cdd.toc.last++;
342       }
343       while (cdd.toc.last < 21);
344     }
345     else if (strstr(header + 0x180,"T-127015") != NULL)
346     {
347       /* Lunar - The Silver Star */
348       cdd.toc.last = cdd.toc.end = 0;
349       do
350       {
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;
354         cdd.toc.last++;
355       }
356       while (cdd.toc.last < 52);
357     }
358     else if (strstr(header + 0x180,"T-113045") != NULL)
359     {
360       /* Shadow of the Beast II */
361       cdd.toc.last = cdd.toc.end = 0;
362       do
363       {
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;
367         cdd.toc.last++;
368       }
369       while (cdd.toc.last < 15);
370     }
371     else if (strstr(header + 0x180,"T-143025") != NULL)
372     {
373       /* Dungeon Explorer */
374       cdd.toc.last = cdd.toc.end = 0;
375       do
376       {
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;
380         cdd.toc.last++;
381       }
382       while (cdd.toc.last < 13);
383     }
384     else if (strstr(header + 0x180,"MK-4410") != NULL)
385     {
386       /* Final Fight CD (USA, Europe) */
387       cdd.toc.last = cdd.toc.end = 0;
388       do
389       {
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;
393         cdd.toc.last++;
394       }
395       while (cdd.toc.last < 26);
396     }
397     else if (strstr(header + 0x180,"G-6013") != NULL)
398     {
399       /* Final Fight CD (Japan) */
400       cdd.toc.last = cdd.toc.end = 0;
401       do
402       {
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;
406         cdd.toc.last++;
407       }
408       while (cdd.toc.last < 29);
409     }
410 #if 0
411     else
412     {
413       /* default TOC (99 tracks & 2s per audio tracks) */
414       do
415       {
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;
419         cdd.toc.last++;
420       }
421       while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
422     }
423 #endif
424   }
425
426   /* Lead-out */
427   cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
428
429   /* CD loaded */
430   cdd.loaded = 1;
431
432   /* disc not scanned yet */
433   cdd.status = NO_DISC;
434
435   return 0;
436 }
437
438 int cdd_unload(void)
439 {
440   int was_loaded = cdd.loaded;
441
442   if (cdd.loaded)
443   {
444     int i;
445
446     /* close CD tracks */
447     if (cdd.toc.tracks[0].fd)
448     {
449       pm_close(cdd.toc.tracks[0].fd);
450       cdd.toc.tracks[0].fd = NULL;
451     }
452
453     for (i = 1; i < cdd.toc.last; i++)
454     {
455 #ifdef USE_LIBTREMOR
456       if (cdd.toc.tracks[i].vf.datasource)
457       {
458         /* close VORBIS file (if still opened) */
459         ov_clear(&cdd.toc.tracks[i].vf);
460       }
461       else
462 #endif
463       if (cdd.toc.tracks[i].fd)
464       {
465         /* close file */
466         if (Pico_mcd->cdda_type == CT_MP3)
467           fclose(cdd.toc.tracks[i].fd);
468         else
469           pm_close(cdd.toc.tracks[0].fd);
470
471         /* detect single file images */
472         if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
473         {
474           /* exit loop */
475           i = cdd.toc.last;
476         }
477       }
478     }
479
480     /* CD unloaded */
481     cdd.loaded = 0;
482
483     if (cdd.status != CD_OPEN)
484       cdd.status = NO_DISC;
485   }
486
487   /* reset TOC */
488   memset(&cdd.toc, 0x00, sizeof(cdd.toc));
489     
490   /* unknown CD image file format */
491   cdd.sectorSize = 0;
492
493   return was_loaded;
494 }
495
496 void cdd_read_data(uint8 *dst)
497 {
498   /* only read DATA track sectors */
499   if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end))
500   {
501     /* BIN format ? */
502     if (cdd.sectorSize == 2352)
503     {
504       /* skip 16-byte header */
505       pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET);
506     }
507
508     /* read sector data (Mode 1 = 2048 bytes) */
509     pm_read(dst, 2048, cdd.toc.tracks[0].fd);
510   }
511 }
512
513 #if 0
514 void cdd_read_audio(unsigned int samples)
515 {
516   /* previous audio outputs */
517   int16 l = cdd.audio[0];
518   int16 r = cdd.audio[1];
519
520   /* get number of internal clocks (samples) needed */
521   samples = blip_clocks_needed(blip[0], samples);
522
523   /* audio track playing ? */
524   if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
525   {
526     int i, mul, delta;
527
528     /* current CD-DA fader volume */
529     int curVol = cdd.volume;
530
531     /* CD-DA fader volume setup (0-1024) */
532     int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
533
534     /* read samples from current block */
535 #ifdef USE_LIBTREMOR
536     if (cdd.toc.tracks[cdd.index].vf.datasource)
537     {
538       int len, done = 0;
539       int16 *ptr = (int16 *) (cdc.ram);
540       samples = samples * 4;
541       while (done < samples)
542       {
543         len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
544         if (len <= 0) 
545         {
546           done = samples;
547           break;
548         }
549         done += len;
550       }
551       samples = done / 4;
552
553       /* process 16-bit (host-endian) stereo samples */
554       for (i=0; i<samples; i++)
555       {
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);
559
560         /* left channel */
561         delta = ((ptr[0] * mul) / 1024) - l;
562         ptr++;
563         l += delta;
564         blip_add_delta_fast(blip[0], i, delta);
565
566         /* right channel */
567         delta = ((ptr[0] * mul) / 1024) - r;
568         ptr++;
569         r += delta;
570         blip_add_delta_fast(blip[1], i, delta);
571
572         /* update CD-DA fader volume (one step/sample) */
573         if (curVol < endVol)
574         {
575           /* fade-in */
576           curVol++;
577         }
578         else if (curVol > endVol)
579         {
580           /* fade-out */
581           curVol--;
582         }
583         else if (!curVol)
584         {
585           /* audio will remain muted until next setup */
586           break;
587         }
588       }
589     }
590     else
591 #endif
592     {
593 #ifdef LSB_FIRST
594       int16 *ptr = (int16 *) (cdc.ram);
595 #else
596       uint8 *ptr = cdc.ram;
597 #endif
598       fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
599
600       /* process 16-bit (little-endian) stereo samples */
601       for (i=0; i<samples; i++)
602       {
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);
606
607         /* left channel */
608   #ifdef LSB_FIRST
609         delta = ((ptr[0] * mul) / 1024) - l;
610         ptr++;
611   #else
612         delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
613         ptr += 2;
614   #endif
615         l += delta;
616         blip_add_delta_fast(blip[0], i, delta);
617
618         /* right channel */
619   #ifdef LSB_FIRST
620         delta = ((ptr[0] * mul) / 1024) - r;
621         ptr++;
622   #else
623         delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
624         ptr += 2;
625   #endif
626         r += delta;
627         blip_add_delta_fast(blip[1], i, delta);
628
629         /* update CD-DA fader volume (one step/sample) */
630         if (curVol < endVol)
631         {
632           /* fade-in */
633           curVol++;
634         }
635         else if (curVol > endVol)
636         {
637           /* fade-out */
638           curVol--;
639         }
640         else if (!curVol)
641         {
642           /* audio will remain muted until next setup */
643           break;
644         }
645       }
646     }
647
648     /* save current CD-DA fader volume */
649     cdd.volume = curVol;
650
651     /* save last audio output for next frame */
652     cdd.audio[0] = l;
653     cdd.audio[1] = r;
654   }
655   else
656   {
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);
660
661     /* save audio output for next frame */
662     cdd.audio[0] = 0;
663     cdd.audio[1] = 0;
664   }
665
666   /* end of Blip Buffer timeframe */
667   blip_end_frame(blip[0], samples);
668   blip_end_frame(blip[1], samples);
669 }
670 #endif
671
672
673 void cdd_update(void)
674 {  
675 #ifdef LOG_CDD
676   error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
677 #endif
678   
679   /* seeking disc */
680   if (cdd.status == CD_SEEK)
681   {
682     /* drive latency */
683     if (cdd.latency > 0)
684     {
685       cdd.latency--;
686       return;
687     }
688
689     /* drive is ready */
690     cdd.status = CD_READY;
691   }
692
693   /* reading disc */
694   else if (cdd.status == CD_PLAY)
695   {
696     /* drive latency */
697     if (cdd.latency > 0)
698     {
699       cdd.latency--;
700       return;
701     }
702
703     /* track type */
704     if (!cdd.index)
705     {
706       /* DATA sector header (CD-ROM Mode 1) */
707       uint8 header[4];
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)];
712       header[3] = 0x01;
713
714       /* data track sector read is controlled by CDC */
715       cdd.lba += cdc_decoder_update(header);
716     }
717     else if (cdd.index < cdd.toc.last)
718     {
719       uint8 header[4] = { 0, };
720
721       /* check against audio track start index */
722       if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
723       {
724         /* audio track playing */
725         Pico_mcd->s68k_regs[0x36+0] = 0x00;
726       }
727
728       /* audio blocks are still sent to CDC as well as CD DAC/Fader */
729       cdc_decoder_update(header);
730  
731       /* next audio block is automatically read */
732       cdd.lba++;
733     }
734     else
735     {
736       /* end of disc */
737       cdd.status = CD_END;
738       return;
739     }
740
741     /* check end of current track */
742     if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
743     {
744 #ifdef USE_LIBTREMOR
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)
748       {
749         ogg_free(cdd.index);
750       }
751 #endif
752 #endif
753       /* play next track */
754       cdd.index++;
755
756       /* PAUSE between tracks */
757       Pico_mcd->s68k_regs[0x36+0] = 0x01;
758
759       /* seek to next audio track start */
760 #ifdef USE_LIBTREMOR
761       if (cdd.toc.tracks[cdd.index].vf.seekable)
762       {
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);
766 #endif
767         ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset);
768       }
769       else
770 #endif 
771 #if 0
772       if (cdd.toc.tracks[cdd.index].fd)
773       {
774         fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
775       }
776 #else
777       {
778         cdd_change_track(cdd.index, cdd.lba);
779       }
780 #endif
781     }
782   }
783
784   /* scanning disc */
785   else if (cdd.status == CD_SCAN)
786   {
787     /* fast-forward or fast-rewind */
788     cdd.lba += cdd.scanOffset;
789
790     /* check current track limits */
791     if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
792     {
793 #ifdef USE_LIBTREMOR
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)
797       {
798         ogg_free(cdd.index);
799       }
800 #endif
801 #endif
802       /* next track */
803       cdd.index++;
804
805       /* skip directly to track start position */
806       cdd.lba = cdd.toc.tracks[cdd.index].start;
807       
808       /* AUDIO track playing ? */
809       if (cdd.status == CD_PLAY)
810       {
811         Pico_mcd->s68k_regs[0x36+0] = 0x00;
812       }
813     }
814     else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
815     {
816 #ifdef USE_LIBTREMOR
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)
820       {
821         ogg_free(cdd.index);
822       }
823 #endif
824 #endif
825
826       /* previous track */
827       cdd.index--;
828
829       /* skip directly to track end position */
830       cdd.lba = cdd.toc.tracks[cdd.index].end;
831     }
832
833     /* check disc limits */
834     if (cdd.index < 0)
835     {
836       cdd.index = 0;
837       cdd.lba = 0;
838     }
839     else if (cdd.index >= cdd.toc.last)
840     {
841       /* no AUDIO track playing */
842       Pico_mcd->s68k_regs[0x36+0] = 0x01;
843
844       /* end of disc */
845       cdd.index = cdd.toc.last;
846       cdd.lba = cdd.toc.end;
847       cdd.status = CD_END;
848       return;
849     }
850
851     /* seek to current block */
852     if (!cdd.index)
853     {
854       /* no AUDIO track playing */
855       Pico_mcd->s68k_regs[0x36+0] = 0x01;
856
857       /* DATA track */
858       pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET);
859     }
860 #ifdef USE_LIBTREMOR
861     else if (cdd.toc.tracks[cdd.index].vf.seekable)
862     {
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)
866       {
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);
869       }
870 #endif
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);
873     }
874 #endif 
875 #if 0
876     else if (cdd.toc.tracks[cdd.index].fd)
877     {
878       /* PCM AUDIO track */
879       fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
880     }
881 #else
882     else
883     {
884       cdd_change_track(cdd.index, cdd.lba);
885     }
886 #endif
887   }
888 }
889
890 #define set_reg16(r, v) { \
891   uint16 _v = v; \
892   Pico_mcd->s68k_regs[(r)] = _v >> 8; \
893   Pico_mcd->s68k_regs[(r)+1] = _v; \
894 }
895
896 void cdd_process(void)
897 {
898   /* Process CDD command */
899   switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f)
900   {
901     case 0x00:  /* Drive Status */
902     {
903       /* RS1-RS8 normally unchanged */
904       Pico_mcd->s68k_regs[0x38+0] = cdd.status;
905
906       /* unless RS1 indicated invalid track infos */
907       if (Pico_mcd->s68k_regs[0x38+1] == 0x0f)
908       {
909         /* and SEEK has ended */
910         if (cdd.status != CD_SEEK)
911         {
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);
915         }
916       }
917       break;
918     }
919
920     case 0x01:  /* Stop Drive */
921     {
922       /* update status */
923       cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
924
925       /* no audio track playing */
926       Pico_mcd->s68k_regs[0x36+0] = 0x01;
927
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);
934       return;
935     }
936
937     case 0x02:  /* Read TOC */
938     {
939       if (cdd.status == NO_DISC)
940         cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
941
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])
945       {
946         case 0x00:  /* Current Absolute Time (MM:SS:FF) */
947         {
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) */
954           break;
955         }
956
957         case 0x01:  /* Current Track Relative Time (MM:SS:FF) */
958         {
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) */
965           break;
966         }
967
968         case 0x02:  /* Current Track Number */
969         {
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;
975           break;
976         }
977
978         case 0x03:  /* Total length (MM:SS:FF) */
979         {
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;
986           break;
987         }
988
989         case 0x04:  /* First & Last Track Numbers */
990         {
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) */
996           break;
997         }
998
999         case 0x05:  /* Track Start Time (MM:SS:FF) */
1000         {
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) */
1008           if (track == 1)
1009           {
1010             /* RS6 bit 3 is set for the first (DATA) track */
1011             Pico_mcd->s68k_regs[0x3e + 0] |= 0x08;
1012           }
1013           break;
1014         }
1015
1016         default:
1017         {
1018 #ifdef LOG_ERROR
1019           error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc);
1020 #endif
1021           return;
1022         }
1023       }
1024       break;
1025     }
1026
1027     case 0x03:  /* Play  */
1028     {
1029       /* reset track index */
1030       int index = 0;
1031
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;
1036
1037       /* CD drive latency */
1038       if (!cdd.latency)
1039       {
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 */
1045         cdd.latency = 10;
1046       }
1047
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).        */
1053       if (lba > cdd.lba)
1054       {
1055         cdd.latency += (((lba - cdd.lba) * 120) / 270000);
1056       }
1057       else 
1058       {
1059         cdd.latency += (((cdd.lba - lba) * 120) / 270000);
1060       }
1061
1062       /* update current LBA */
1063       cdd.lba = lba;
1064
1065       /* get track index */
1066       while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1067
1068 #ifdef USE_LIBTREMOR
1069 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1070       /* check if track index has changed */
1071       if (index != cdd.index)
1072       {
1073         /* close previous track VORBIS file structure to save memory */
1074         if (cdd.toc.tracks[cdd.index].vf.datasource)
1075         {
1076           ogg_free(cdd.index);
1077         }
1078
1079         /* open current track VORBIS file */
1080         if (cdd.toc.tracks[index].vf.seekable)
1081         {
1082           ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1083         }
1084       }
1085 #endif
1086 #endif
1087
1088       /* update current track index */
1089       cdd.index = index;
1090
1091       /* stay within track limits when seeking files */
1092       if (lba < cdd.toc.tracks[index].start) 
1093       {
1094         lba = cdd.toc.tracks[index].start;
1095       }
1096       
1097       /* seek to current block */
1098       if (!index)
1099       {
1100         /* DATA track */
1101         pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1102       }
1103 #ifdef USE_LIBTREMOR
1104       else if (cdd.toc.tracks[index].vf.seekable)
1105       {
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);
1108       }
1109 #endif
1110 #if 0
1111       else if (cdd.toc.tracks[index].fd)
1112       {
1113         /* PCM AUDIO track */
1114         fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1115       }
1116 #else
1117       else
1118       {
1119         cdd_change_track(index, lba);
1120       }
1121 #endif
1122
1123       /* no audio track playing (yet) */
1124       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1125
1126       /* update status */
1127       cdd.status = CD_PLAY;
1128
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;
1135       break;
1136     }
1137
1138     case 0x04:  /* Seek */
1139     {
1140       /* reset track index */
1141       int index = 0;
1142
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;
1147
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) */
1152       if (lba > cdd.lba)
1153       {
1154         cdd.latency = ((lba - cdd.lba) * 120) / 270000;
1155       }
1156       else
1157       {
1158         cdd.latency = ((cdd.lba - lba) * 120) / 270000;
1159       }
1160
1161       /* update current LBA */
1162       cdd.lba = lba;
1163
1164       /* get current track index */
1165       while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
1166
1167 #ifdef USE_LIBTREMOR
1168 #ifdef DISABLE_MANY_OGG_OPEN_FILES
1169       /* check if track index has changed */
1170       if (index != cdd.index)
1171       {
1172         /* close previous track VORBIS file structure to save memory */
1173         if (cdd.toc.tracks[cdd.index].vf.datasource)
1174         {
1175           ogg_free(cdd.index);
1176         }
1177
1178         /* open current track VORBIS file */
1179         if (cdd.toc.tracks[index].vf.seekable)
1180         {
1181           ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
1182         }
1183       }
1184 #endif
1185 #endif
1186
1187       /* update current track index */
1188       cdd.index = index;
1189
1190       /* stay within track limits */
1191       if (lba < cdd.toc.tracks[index].start) 
1192       {
1193         lba = cdd.toc.tracks[index].start;
1194       }
1195       
1196       /* seek to current block */
1197       if (!index)
1198       {
1199         /* DATA track */
1200         pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET);
1201       }
1202 #ifdef USE_LIBTREMOR
1203       else if (cdd.toc.tracks[index].vf.seekable)
1204       {
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);
1207       }
1208 #endif
1209 #if 0
1210       else if (cdd.toc.tracks[index].fd)
1211       {
1212         /* PCM AUDIO track */
1213         fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET);
1214       }
1215 #endif
1216
1217       /* no audio track playing */
1218       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1219
1220       /* update status */
1221       cdd.status = CD_SEEK;
1222
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);
1229       return;
1230     }
1231
1232     case 0x06:  /* Pause */
1233     {
1234       /* no audio track playing */
1235       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1236
1237       /* update status (RS1-RS8 unchanged) */
1238       cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1239       break;
1240     }
1241
1242     case 0x07:  /* Resume */
1243     {
1244       /* update status (RS1-RS8 unchanged) */
1245       cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY;
1246       break;
1247     }
1248
1249     case 0x08:  /* Forward Scan */
1250     {
1251       /* reset scanning direction / speed */
1252       cdd.scanOffset = CD_SCAN_SPEED;
1253
1254       /* update status (RS1-RS8 unchanged) */
1255       cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1256       break;
1257     }
1258
1259     case 0x09:  /* Rewind Scan */
1260     {
1261       /* reset scanning direction / speed */
1262       cdd.scanOffset = -CD_SCAN_SPEED;
1263
1264       /* update status (RS1-RS8 unchanged) */
1265       cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN;
1266       break;
1267     }
1268
1269
1270     case 0x0a:  /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */
1271     {
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 */
1276
1277       /* no audio track playing */
1278       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1279
1280       /* update status (RS1-RS8 unchanged) */
1281       cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
1282       break;
1283     }
1284
1285     case 0x0c:  /* Close Tray */
1286     {
1287       /* no audio track playing */
1288       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1289
1290       /* update status */
1291       cdd.status = cdd.loaded ? CD_STOP : NO_DISC;
1292
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);
1299
1300       if (PicoMCDcloseTray)
1301         PicoMCDcloseTray();
1302
1303       return;
1304     }
1305
1306     case 0x0d:  /* Open Tray */
1307     {
1308       /* no audio track playing */
1309       Pico_mcd->s68k_regs[0x36+0] = 0x01;
1310
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);
1318
1319       if (PicoMCDopenTray)
1320         PicoMCDopenTray();
1321       return;
1322     }
1323
1324     default:  /* Unknown command */
1325 #ifdef LOG_CDD
1326       error("Unknown CDD Command !!!\n");
1327 #endif
1328       Pico_mcd->s68k_regs[0x38+0] = cdd.status;
1329       break;
1330   }
1331
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;
1339 }
1340
1341 // vim:shiftwidth=2:ts=2:expandtab