pandora: fix readme and pxml version
[picodrive.git] / pico / cd / cdd.c
... / ...
CommitLineData
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 "cd_parse.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#define is_audio(index) \
53 (cdd.toc.tracks[index].type & CT_AUDIO)
54
55/* BCD conversion lookup tables */
56static const uint8 lut_BCD_8[100] =
57{
58 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
59 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
60 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
61 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
62 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
63 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
64 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
65 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
66 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
67 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
68};
69
70static const uint16 lut_BCD_16[100] =
71{
72 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
73 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
74 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209,
75 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309,
76 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409,
77 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509,
78 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609,
79 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709,
80 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809,
81 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
82};
83
84/* pre-build TOC */
85static const uint16 toc_snatcher[21] =
86{
87 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681,
88 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485,
89 31380
90};
91
92static const uint16 toc_lunar[52] =
93{
94 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870,
95 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263,
96 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205,
97 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549,
98 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132,
99 685, 3167
100};
101
102static const uint32 toc_shadow[15] =
103{
104 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792,
105 11637, 2547, 2521, 3856, 900
106};
107
108static const uint32 toc_dungeon[13] =
109{
110 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100,
111 3325, 6825, 25275
112};
113
114static const uint32 toc_ffight[26] =
115{
116 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764,
117 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024,
118 14562, 10320, 8627, 3795, 3047
119};
120
121static const uint32 toc_ffightj[29] =
122{
123 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763,
124 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026,
125 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052
126};
127
128#if 0
129/* supported WAVE file header (16-bit stereo samples @44.1kHz) */
130static const unsigned char waveHeader[32] =
131{
132 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,
133 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61
134};
135#endif
136
137#ifdef USE_LIBTREMOR
138#ifdef DISABLE_MANY_OGG_OPEN_FILES
139static void ogg_free(int i)
140{
141 /* clear OGG file descriptor to prevent file from being closed */
142 cdd.toc.tracks[i].vf.datasource = NULL;
143
144 /* close VORBIS file structure */
145 ov_clear(&cdd.toc.tracks[i].vf);
146
147 /* indicates that the track is a seekable VORBIS file */
148 cdd.toc.tracks[i].vf.seekable = 1;
149
150 /* reset file reading position */
151 fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET);
152}
153#endif
154#endif
155
156static off_t read_pos = -1;
157
158void cdd_reset(void)
159{
160 /* stop audio streaming */
161 Pico_mcd->cdda_stream = NULL;
162
163 /* reset cycle counter */
164 cdd.cycles = 0;
165
166 /* reset drive access latency */
167 cdd.latency = 0;
168
169 /* reset track index */
170 cdd.index = 0;
171
172 /* reset logical block address */
173 cdd.lba = 0;
174
175 /* reset status */
176 cdd.status = NO_DISC;
177
178 /* reset CD-DA fader (full volume) */
179 cdd.volume = 0x400;
180
181 /* clear CD-DA output */
182 cdd.audio[0] = cdd.audio[1] = 0;
183
184 /* no audio track playing */
185 Pico_mcd->s68k_regs[0x36+0] = 0x01;
186 /* reset file read position */
187 read_pos = -1;
188}
189
190/* FIXME: use cdd_read_audio() instead */
191void cdd_play_audio(int index, int lba)
192{
193 int i, base, lba_offset, lb_len;
194
195 for (i = index; i >= 0; i--)
196 if (cdd.toc.tracks[i].fd != NULL)
197 break;
198 // prevent playing from file with binary track if MD+ (Doom Fusion)
199 // TODO: this doesn't cover all tracks being in a single bin file properly:
200 // in that case, fd should be duplicated to work properly with this MD+ shit.
201 if (! is_audio(index) || (read_pos >= 0 && cdd.index == i && ! is_audio(i)))
202 return;
203
204 Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd;
205 Pico_mcd->cdda_type = cdd.toc.tracks[i].type;
206 base = cdd.toc.tracks[index].offset;
207 lba_offset = lba - cdd.toc.tracks[index].start;
208 lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start;
209
210 elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base);
211
212 cdda_start_play(base, lba_offset, lb_len);
213}
214
215static void cdd_seek(int index, int lba)
216{
217#ifdef USE_LIBTREMOR
218#ifdef DISABLE_MANY_OGG_OPEN_FILES
219 /* close previous track VORBIS file structure to save memory */
220 if (is_audio(cdd.index) && cdd.toc.tracks[cdd.index].vf.datasource)
221 {
222 ogg_free(cdd.index);
223 }
224
225 /* open current track VORBIS file */
226 if (is_audio(index) && cdd.toc.tracks[index].vf.seekable)
227 {
228 ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0);
229 }
230#endif
231#endif
232
233 /* update current track index and LBA */
234 cdd.index = (index < 0 ? 0 : index);
235 cdd.lba = lba;
236 if (index < 0) return;
237
238 /* stay within track limits when seeking files */
239 if (lba < cdd.toc.tracks[cdd.index].start)
240 {
241 lba = cdd.toc.tracks[cdd.index].start;
242 }
243
244 /* seek to current block */
245 if (!is_audio(cdd.index))
246 {
247 /* DATA track */
248 read_pos = lba * cdd.sectorSize;
249 pm_seek(cdd.toc.tracks[cdd.index].fd, read_pos, SEEK_SET);
250 }
251#ifdef USE_LIBTREMOR
252 else if (cdd.toc.tracks[cdd.index].vf.seekable)
253 {
254 /* VORBIS AUDIO track */
255 ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset);
256 }
257#endif
258#if 0
259 else if (cdd.toc.tracks[cdd.index].fd)
260 {
261 /* PCM AUDIO track */
262 fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET);
263 }
264#else
265 else
266 {
267 cdd_play_audio(cdd.index, lba);
268 }
269#endif
270}
271
272int cdd_context_save(uint8 *state)
273{
274 int bufferptr = 0;
275
276 save_param(&cdd.cycles, sizeof(cdd.cycles));
277 save_param(&cdd.latency, sizeof(cdd.latency));
278 save_param(&cdd.index, sizeof(cdd.index));
279 save_param(&cdd.lba, sizeof(cdd.lba));
280 save_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
281 save_param(&cdd.volume, sizeof(cdd.volume));
282 save_param(&cdd.status, sizeof(cdd.status));
283
284 return bufferptr;
285}
286
287int cdd_context_load(uint8 *state)
288{
289 int bufferptr = 0;
290
291 load_param(&cdd.cycles, sizeof(cdd.cycles));
292 load_param(&cdd.latency, sizeof(cdd.latency));
293 load_param(&cdd.index, sizeof(cdd.index));
294 load_param(&cdd.lba, sizeof(cdd.lba));
295 load_param(&cdd.scanOffset, sizeof(cdd.scanOffset));
296 load_param(&cdd.volume, sizeof(cdd.volume));
297 load_param(&cdd.status, sizeof(cdd.status));
298
299 /* seek to current track position */
300 cdd_seek(cdd.index, cdd.lba);
301
302 return bufferptr;
303}
304
305int cdd_context_load_old(uint8 *state)
306{
307 memcpy(&cdd.lba, state + 8, sizeof(cdd.lba));
308 cdd_seek(cdd.index, cdd.lba);
309
310 return 12 * 4;
311}
312
313int cdd_load(const char *filename, int type)
314{
315 char header[0x210];
316 int ret;
317
318 /* first unmount any loaded disc */
319 cdd_unload();
320
321 /* genplus parses cue here, in PD we use our own parser */
322 ret = load_cd_image(filename, &type);
323 if (ret != 0)
324 return ret;
325
326 if (type == CT_ISO) {
327 /* ISO format (2048 bytes data blocks) */
328 cdd.sectorSize = 2048;
329 } else {
330 /* audio or BIN format (2352 bytes data blocks) */
331 cdd.sectorSize = 2352;
332 }
333
334 /* read first 16 bytes */
335 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
336
337 /* look for valid CD image ID string */
338 if (!Pico.romsize && memcmp("SEGADISCSYSTEM", header, 14))
339 {
340 /* if not found, read next 16 bytes */
341 pm_read(header, 0x10, cdd.toc.tracks[0].fd);
342
343 /* look again for valid CD image ID string */
344 if (memcmp("SEGADISCSYSTEM", header, 14))
345 {
346 elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?");
347 /* assume bin without security code */
348 }
349 }
350
351 pm_sectorsize(cdd.sectorSize, cdd.toc.tracks[0].fd);
352
353 /* Simulate audio tracks if none found */
354 if (!Pico.romsize && cdd.toc.last == 1)
355 {
356 /* read CD image header + security code */
357 pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd);
358
359 /* Some games require exact TOC infos */
360 if (strstr(header + 0x180,"T-95035") != NULL)
361 {
362 /* Snatcher */
363 cdd.toc.last = cdd.toc.end = 0;
364 do
365 {
366 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
367 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
368 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
369 cdd.toc.last++;
370 }
371 while (cdd.toc.last < 21);
372 }
373 else if (strstr(header + 0x180,"T-127015") != NULL)
374 {
375 /* Lunar - The Silver Star */
376 cdd.toc.last = cdd.toc.end = 0;
377 do
378 {
379 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
380 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
381 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
382 cdd.toc.last++;
383 }
384 while (cdd.toc.last < 52);
385 }
386 else if (strstr(header + 0x180,"T-113045") != NULL)
387 {
388 /* Shadow of the Beast II */
389 cdd.toc.last = cdd.toc.end = 0;
390 do
391 {
392 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
393 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
394 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
395 cdd.toc.last++;
396 }
397 while (cdd.toc.last < 15);
398 }
399 else if (strstr(header + 0x180,"T-143025") != NULL)
400 {
401 /* Dungeon Explorer */
402 cdd.toc.last = cdd.toc.end = 0;
403 do
404 {
405 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
406 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
407 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
408 cdd.toc.last++;
409 }
410 while (cdd.toc.last < 13);
411 }
412 else if (strstr(header + 0x180,"MK-4410") != NULL)
413 {
414 /* Final Fight CD (USA, Europe) */
415 cdd.toc.last = cdd.toc.end = 0;
416 do
417 {
418 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
419 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
420 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
421 cdd.toc.last++;
422 }
423 while (cdd.toc.last < 26);
424 }
425 else if (strstr(header + 0x180,"G-6013") != NULL)
426 {
427 /* Final Fight CD (Japan) */
428 cdd.toc.last = cdd.toc.end = 0;
429 do
430 {
431 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
432 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
433 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
434 cdd.toc.last++;
435 }
436 while (cdd.toc.last < 29);
437 }
438#if 0
439 else
440 {
441 /* default TOC (99 tracks & 2s per audio tracks) */
442 do
443 {
444 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
445 cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
446 cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
447 cdd.toc.last++;
448 }
449 while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
450 }
451#endif
452 }
453
454 /* Lead-out */
455 cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
456
457 /* CD loaded */
458 cdd.loaded = 1;
459
460 /* disc not scanned yet */
461 cdd.status = NO_DISC;
462
463 return 0;
464}
465
466int cdd_unload(void)
467{
468 int was_loaded = cdd.loaded;
469
470 if (cdd.loaded)
471 {
472 int i;
473
474 /* stop audio streaming */
475 if (Pico_mcd) Pico_mcd->cdda_stream = NULL;
476
477 /* close CD tracks */
478 if (cdd.toc.tracks[0].fd)
479 {
480 pm_close(cdd.toc.tracks[0].fd);
481 cdd.toc.tracks[0].fd = NULL;
482 if (cdd.toc.tracks[0].fname)
483 free(cdd.toc.tracks[0].fname);
484 cdd.toc.tracks[0].fname = NULL;
485 }
486
487 for (i = 1; i < cdd.toc.last; i++)
488 {
489#ifdef USE_LIBTREMOR
490 if (cdd.toc.tracks[i].vf.datasource)
491 {
492 /* close VORBIS file (if still opened) */
493 ov_clear(&cdd.toc.tracks[i].vf);
494 }
495 else
496#endif
497 if (cdd.toc.tracks[i].fd)
498 {
499 /* close file */
500 if (cdd.toc.tracks[i].type == CT_MP3)
501 fclose(cdd.toc.tracks[i].fd);
502 else
503 pm_close(cdd.toc.tracks[i].fd);
504 cdd.toc.tracks[i].fd = NULL;
505 if (cdd.toc.tracks[i].fname)
506 free(cdd.toc.tracks[i].fname);
507 cdd.toc.tracks[i].fname = NULL;
508
509 /* detect single file images */
510 if (cdd.toc.tracks[i+1].fd == cdd.toc.tracks[i].fd)
511 {
512 /* exit loop */
513 i = cdd.toc.last;
514 }
515 }
516 }
517
518 /* CD unloaded */
519 cdd.loaded = 0;
520
521 if (cdd.status != CD_OPEN)
522 cdd.status = NO_DISC;
523 }
524
525 /* reset TOC */
526 memset(&cdd.toc, 0x00, sizeof(cdd.toc));
527
528 /* unknown CD image file format */
529 cdd.sectorSize = 0;
530
531 return was_loaded;
532}
533
534void cdd_read_data(uint8 *dst)
535{
536 /* only read DATA track sectors */
537 if (!is_audio(cdd.index) && (cdd.lba >= cdd.toc.tracks[cdd.index].start) &&
538 (cdd.lba < cdd.toc.tracks[cdd.index].end))
539 {
540 off_t pos;
541
542 /* BIN format ? */
543 if (cdd.sectorSize == 2352)
544 {
545 /* skip 16-byte header */
546 pos = cdd.lba * 2352 + 16;
547 }
548 else
549 {
550 pos = cdd.lba * cdd.sectorSize;
551 }
552
553 if (pos != read_pos) {
554 pm_seek(cdd.toc.tracks[cdd.index].fd, pos, SEEK_SET);
555 read_pos = pos;
556 }
557
558 /* read sector data (Mode 1 = 2048 bytes) */
559 read_pos += pm_read(dst, 2048, cdd.toc.tracks[cdd.index].fd);
560 }
561}
562
563#if 0
564void cdd_read_audio(unsigned int samples)
565{
566 /* previous audio outputs */
567 int16 l = cdd.audio[0];
568 int16 r = cdd.audio[1];
569
570 /* get number of internal clocks (samples) needed */
571 samples = blip_clocks_needed(blip[0], samples);
572
573 /* audio track playing ? */
574 if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd)
575 {
576 int i, mul, delta;
577
578 /* current CD-DA fader volume */
579 int curVol = cdd.volume;
580
581 /* CD-DA fader volume setup (0-1024) */
582 int endVol = Pico_mcd->regs[0x34>>1].w >> 4;
583
584 /* read samples from current block */
585#ifdef USE_LIBTREMOR
586 if (cdd.toc.tracks[cdd.index].vf.datasource)
587 {
588 int len, done = 0;
589 int16 *ptr = (int16 *) (cdc.ram);
590 samples = samples * 4;
591 while (done < samples)
592 {
593 len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0);
594 if (len <= 0)
595 {
596 done = samples;
597 break;
598 }
599 done += len;
600 }
601 samples = done / 4;
602
603 /* process 16-bit (host-endian) stereo samples */
604 for (i=0; i<samples; i++)
605 {
606 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
607 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
608 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
609
610 /* left channel */
611 delta = ((ptr[0] * mul) / 1024) - l;
612 ptr++;
613 l += delta;
614 blip_add_delta_fast(blip[0], i, delta);
615
616 /* right channel */
617 delta = ((ptr[0] * mul) / 1024) - r;
618 ptr++;
619 r += delta;
620 blip_add_delta_fast(blip[1], i, delta);
621
622 /* update CD-DA fader volume (one step/sample) */
623 if (curVol < endVol)
624 {
625 /* fade-in */
626 curVol++;
627 }
628 else if (curVol > endVol)
629 {
630 /* fade-out */
631 curVol--;
632 }
633 else if (!curVol)
634 {
635 /* audio will remain muted until next setup */
636 break;
637 }
638 }
639 }
640 else
641#endif
642 {
643#ifdef LSB_FIRST
644 int16 *ptr = (int16 *) (cdc.ram);
645#else
646 uint8 *ptr = cdc.ram;
647#endif
648 fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
649
650 /* process 16-bit (little-endian) stereo samples */
651 for (i=0; i<samples; i++)
652 {
653 /* CD-DA fader multiplier (cf. LC7883 datasheet) */
654 /* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
655 mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
656
657 /* left channel */
658 #ifdef LSB_FIRST
659 delta = ((ptr[0] * mul) / 1024) - l;
660 ptr++;
661 #else
662 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - l;
663 ptr += 2;
664 #endif
665 l += delta;
666 blip_add_delta_fast(blip[0], i, delta);
667
668 /* right channel */
669 #ifdef LSB_FIRST
670 delta = ((ptr[0] * mul) / 1024) - r;
671 ptr++;
672 #else
673 delta = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024) - r;
674 ptr += 2;
675 #endif
676 r += delta;
677 blip_add_delta_fast(blip[1], i, delta);
678
679 /* update CD-DA fader volume (one step/sample) */
680 if (curVol < endVol)
681 {
682 /* fade-in */
683 curVol++;
684 }
685 else if (curVol > endVol)
686 {
687 /* fade-out */
688 curVol--;
689 }
690 else if (!curVol)
691 {
692 /* audio will remain muted until next setup */
693 break;
694 }
695 }
696 }
697
698 /* save current CD-DA fader volume */
699 cdd.volume = curVol;
700
701 /* save last audio output for next frame */
702 cdd.audio[0] = l;
703 cdd.audio[1] = r;
704 }
705 else
706 {
707 /* no audio output */
708 if (l) blip_add_delta_fast(blip[0], 0, -l);
709 if (r) blip_add_delta_fast(blip[1], 0, -r);
710
711 /* save audio output for next frame */
712 cdd.audio[0] = 0;
713 cdd.audio[1] = 0;
714 }
715
716 /* end of Blip Buffer timeframe */
717 blip_end_frame(blip[0], samples);
718 blip_end_frame(blip[1], samples);
719}
720#endif
721
722
723void cdd_update(void)
724{
725#ifdef LOG_CDD
726