fix clang build
[picodrive.git] / pico / cd / cdd.c
CommitLineData
274fcc35 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
50cdd_t cdd;
51
52/* BCD conversion lookup tables */
53static 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
67static 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 */
82static 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
89static 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
99static 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
105static const uint32 toc_dungeon[13] =
106{
107 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
108 3325, 6825, 25275
109};
110
111static 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
118static 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
ba11a481 125#if 0
274fcc35 126/* supported WAVE file header (16-bit stereo samples @44.1kHz) */
127static 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};
ba11a481 132#endif
274fcc35 133
134#ifdef USE_LIBTREMOR
135#ifdef DISABLE_MANY_OGG_OPEN_FILES
136static 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
153void 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 */
7b3ddc11 168 cdd.status = NO_DISC;
169
274fcc35 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 */
178static 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
196int 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
211int 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
277int cdd_context_load_old(uint8 *state)
278{
279 memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
280 return 12 * 4;
281}
282
283int 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;
7b3ddc11 431
432 /* disc not scanned yet */
433 cdd.status = NO_DISC;
434
274fcc35 435 return 0;
436}
437
438int 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;
7b3ddc11 482
483 if (cdd.status != CD_OPEN)
484 cdd.status = NO_DISC;
274fcc35 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
496void 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
514void 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 ? */
f47d0a28 524 if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
274fcc35 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
673void cdd_update(void)
674{
675#ifdef LOG_CDD
676