1 /*
2 * UAE
3 *
4 * CD image file support
5 *
6 * - iso (2048/2352 block size)
7 * - cue/bin, cue/bin/wav, cue/bin/mp3, cue/bin/flac
8 * - ccd/img and ccd/img/sub
9 * - chd cd
10 *
11 * Copyright 2010-2013 Toni Wilen
12 *
13 */
14 #include "sysconfig.h"
15 #include "sysdeps.h"
16 
17 #ifdef HAVE_SYS_TIMEB_H
18 #include <sys/timeb.h>
19 #else
20 
21 #endif
22 
23 #include "options.h"
24 #include "blkdev.h"
25 #include "zfile.h"
26 #include "gui.h"
27 #include "fsdb.h"
28 #include "threaddep/thread.h"
29 #include "scsidev.h"
30 #include "mp3decoder.h"
31 #include "cda_play.h"
32 #include "uae/memory.h"
33 #include "audio.h"
34 #include "uae.h"
35 #include "uae/cdrom.h"
36 #ifdef RETROPLATFORM
37 #include "rp.h"
38 #endif
39 
40 #ifdef FSUAE
41 #else
42 #define FLAC__NO_DLL
43 #endif // NL
44 
45 #include "FLAC/stream_decoder.h"
46 
47 #ifdef WITH_CHD
48 #include "archivers/chd/chdtypes.h"
49 #include "archivers/chd/chd.h"
50 #include "archivers/chd/chdcd.h"
51 #endif
52 
53 #define scsi_log write_log
54 
55 #define CDDA_BUFFERS 12
56 
57 enum audenc { AUDENC_NONE, AUDENC_PCM, AUDENC_MP3, AUDENC_FLAC, ENC_CHD };
58 
59 struct cdtoc
60 {
61 	struct zfile *handle;
62 	uae_s64 offset;
63 	uae_u8 *data;
64 	struct zfile *subhandle;
65 	int suboffset;
66 	uae_u8 *subdata;
67 
68 	uae_s64 filesize;
69 	TCHAR *fname;
70 	TCHAR *extrainfo;
71 	int address;
72 	uae_u8 adr, ctrl;
73 	int track;
74 	int size;
75 	int skipsize; // bytes to skip after each block
76 	int index1; // distance between index0 and index1
77 	int pregap; // sectors of silence
78 	int postgap; // sectors of silence
79 	audenc enctype;
80 	int writeoffset;
81 	int subcode;
82 #ifdef WITH_CHD
83 	const cdrom_track_info *chdtrack;
84 #endif
85 };
86 
87 struct cdunit {
88 	bool enabled;
89 	bool open;
90 	uae_u8 buffer[2352];
91 	struct cdtoc toc[102];
92 	int tracks;
93 	uae_u64 cdsize;
94 	int blocksize;
95 
96 	int cdda_play_state;
97 	int cdda_play;
98 	int cdda_paused;
99 	int cdda_volume[2];
100 	int cdda_scan;
101 	int cd_last_pos;
102 	int cdda_start, cdda_end;
103 	play_subchannel_callback cdda_subfunc;
104 	play_status_callback cdda_statusfunc;
105 	int cdda_delay, cdda_delay_frames;
106 	bool thread_active;
107 
108 	TCHAR imgname[MAX_DPATH];
109 	uae_sem_t sub_sem;
110 	struct device_info di;
111 #ifdef WITH_CHD
112 	chd_file *chd_f;
113 	cdrom_file *chd_cdf;
114 #endif
115 };
116 
117 static struct cdunit cdunits[MAX_TOTAL_SCSI_DEVICES];
118 static int bus_open;
119 
120 static volatile int cdimage_unpack_thread, cdimage_unpack_active;
121 static smp_comm_pipe unpack_pipe;
122 static uae_sem_t play_sem;
123 
unitisopen(int unitnum)124 static struct cdunit *unitisopen (int unitnum)
125 {
126 	struct cdunit *cdu = &cdunits[unitnum];
127 	if (cdu->open)
128 		return cdu;
129 	return NULL;
130 }
131 
132 
findtoc(struct cdunit * cdu,int * sectorp,bool data)133 static struct cdtoc *findtoc (struct cdunit *cdu, int *sectorp, bool data)
134 {
135 	int i;
136 	int sector;
137 
138 	if (*sectorp < 0)
139 		return NULL;
140 	sector = *sectorp;
141 	for (i = 0; i <= cdu->tracks; i++) {
142 		struct cdtoc *t = &cdu->toc[i];
143 		if (t->address - t->index1 > sector) {
144 			if (i == 0) {
145 				*sectorp = 0;
146 				return t;
147 			}
148 			t--;
149 			sector -= t->address - t->index1;
150 			if (!data && sector < t->pregap)
151 				return NULL; // pregap silence
152 			*sectorp = sector;
153 			return t;
154 		}
155 	}
156 	return NULL;
157 }
158 
do_read(struct cdunit * cdu,struct cdtoc * t,uae_u8 * data,int sector,int offset,int size,bool audio)159 static int do_read (struct cdunit *cdu, struct cdtoc *t, uae_u8 *data, int sector, int offset, int size, bool audio)
160 {
161 	if (t->enctype == ENC_CHD) {
162 #ifdef WITH_CHD
163 		int type = CD_TRACK_MODE1_RAW;
164 		uae_u8 tmpbuf[2352];
165 		if (size > 2352)
166 			return 0;
167 		switch (size)
168 		{
169 			case 2352:
170 			type = CD_TRACK_MODE1_RAW;
171 			break;
172 			case 2336:
173 			type = CD_TRACK_MODE2;
174 			break;
175 			case 2048:
176 			type = CD_TRACK_MODE1;
177 			break;
178 		}
179 		if (audio && size == 2352)
180 			type = CD_TRACK_AUDIO;
181 		if (cdrom_read_data(cdu->chd_cdf, sector + t->offset, tmpbuf, type, true)) {
182 			memcpy(data, tmpbuf + offset, size);
183 			return 1;
184 		}
185 		return 0;
186 #endif
187 	} else if (t->handle) {
188 		int ssize = t->size + t->skipsize;
189 		zfile_fseek (t->handle, t->offset + (uae_u64)sector * ssize + offset, SEEK_SET);
190 		return zfile_fread (data, 1, size, t->handle) == size;
191 	}
192 	return 0;
193 }
194 
195 // WOHOO, library that supports virtual file access functions. Perfect!
flac_metadata_callback(const FLAC__StreamDecoder * decoder,const FLAC__StreamMetadata * metadata,void * client_data)196 static void flac_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
197 {
198 	struct cdtoc *t = (struct cdtoc*)client_data;
199 	if (t->data)
200 		return;
201 	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
202 		t->filesize = metadata->data.stream_info.total_samples * (metadata->data.stream_info.bits_per_sample / 8) * metadata->data.stream_info.channels;
203 	}
204 }
flac_error_callback(const FLAC__StreamDecoder * decoder,FLAC__StreamDecoderErrorStatus status,void * client_data)205 static void flac_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
206 {
207 	return;
208 }
flac_write_callback(const FLAC__StreamDecoder * decoder,const FLAC__Frame * frame,const FLAC__int32 * const buffer[],void * client_data)209 static FLAC__StreamDecoderWriteStatus flac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
210 {
211 	struct cdtoc *t = (struct cdtoc*)client_data;
212 	uae_u16 *p = (uae_u16*)(t->data + t->writeoffset);
213 	int size = 4;
214 	for (int i = 0; i < frame->header.blocksize && t->writeoffset < t->filesize - size; i++, t->writeoffset += size) {
215 		*p++ = (FLAC__int16)buffer[0][i];
216 		*p++ = (FLAC__int16)buffer[1][i];
217 	}
218 	return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
219 }
file_read_callback(const FLAC__StreamDecoder * decoder,FLAC__byte buffer[],size_t * bytes,void * client_data)220 static FLAC__StreamDecoderReadStatus file_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
221 {
222 	struct cdtoc *t = (struct cdtoc*)client_data;
223 	if (zfile_ftell (t->handle) >= zfile_size (t->handle))
224 		return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
225 	return zfile_fread (buffer, *bytes, 1, t->handle) ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_ABORT;
226 }
file_seek_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 absolute_byte_offset,void * client_data)227 static FLAC__StreamDecoderSeekStatus file_seek_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
228 {
229 	struct cdtoc *t = (struct cdtoc*)client_data;
230 	zfile_fseek (t->handle, absolute_byte_offset, SEEK_SET);
231 	return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
232 }
file_tell_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 * absolute_byte_offset,void * client_data)233 static FLAC__StreamDecoderTellStatus file_tell_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
234 {
235 	struct cdtoc *t = (struct cdtoc*)client_data;
236 	*absolute_byte_offset = zfile_ftell (t->handle);
237 	return FLAC__STREAM_DECODER_TELL_STATUS_OK;
238 }
file_len_callback(const FLAC__StreamDecoder * decoder,FLAC__uint64 * stream_length,void * client_data)239 static FLAC__StreamDecoderLengthStatus file_len_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
240 {
241 	struct cdtoc *t = (struct cdtoc*)client_data;
242 	*stream_length = zfile_size (t->handle);
243 	return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
244 }
file_eof_callback(const FLAC__StreamDecoder * decoder,void * client_data)245 static FLAC__bool file_eof_callback (const FLAC__StreamDecoder *decoder, void *client_data)
246 {
247 	struct cdtoc *t = (struct cdtoc*)client_data;
248 	return zfile_ftell (t->handle) >= zfile_size (t->handle);
249 }
250 
flac_get_size(struct cdtoc * t)251 static void flac_get_size (struct cdtoc *t)
252 {
253 	FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new ();
254 	if (decoder) {
255 		FLAC__stream_decoder_set_md5_checking (decoder, false);
256 		int init_status = FLAC__stream_decoder_init_stream (decoder,
257 			&file_read_callback, &file_seek_callback, &file_tell_callback,
258 			&file_len_callback, &file_eof_callback,
259 			&flac_write_callback, &flac_metadata_callback, &flac_error_callback, t);
260 		FLAC__stream_decoder_process_until_end_of_metadata (decoder);
261 		FLAC__stream_decoder_delete (decoder);
262 	}
263 }
flac_get_data(struct cdtoc * t)264 static uae_u8 *flac_get_data (struct cdtoc *t)
265 {
266 	write_log (_T("FLAC: unpacking '%s'..\n"), zfile_getname (t->handle));
267 	t->writeoffset = 0;
268 	FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new ();
269 	if (decoder) {
270 		FLAC__stream_decoder_set_md5_checking (decoder, false);
271 		int init_status = FLAC__stream_decoder_init_stream (decoder,
272 			&file_read_callback, &file_seek_callback, &file_tell_callback,
273 			&file_len_callback, &file_eof_callback,
274 			&flac_write_callback, &flac_metadata_callback, &flac_error_callback, t);
275 		FLAC__stream_decoder_process_until_end_of_stream (decoder);
276 		FLAC__stream_decoder_delete (decoder);
277 		write_log (_T("FLAC: %s unpacked\n"), zfile_getname (t->handle));
278 	}
279 	return t->data;
280 }
281 
sub_to_interleaved(const uae_u8 * s,uae_u8 * d)282 void sub_to_interleaved (const uae_u8 *s, uae_u8 *d)
283 {
284 	for (int i = 0; i < 8 * SUB_ENTRY_SIZE; i ++) {
285 		int dmask = 0x80;
286 		int smask = 1 << (7 - (i & 7));
287 		(*d) = 0;
288 		for (int j = 0; j < 8; j++) {
289 			(*d) |= (s[(i / 8) + j * SUB_ENTRY_SIZE] & smask) ? dmask : 0;
290 			dmask >>= 1;
291 		}
292 		d++;
293 	}
294 }
sub_to_deinterleaved(const uae_u8 * s,uae_u8 * d)295 void sub_to_deinterleaved (const uae_u8 *s, uae_u8 *d)
296 {
297 	for (int i = 0; i < 8 * SUB_ENTRY_SIZE; i ++) {
298 		int dmask = 0x80;
299 		int smask = 1 << (7 - (i / SUB_ENTRY_SIZE));
300 		(*d) = 0;
301 		for (int j = 0; j < 8; j++) {
302 			(*d) |= (s[(i % SUB_ENTRY_SIZE) * 8 + j] & smask) ? dmask : 0;
303 			dmask >>= 1;
304 		}
305 		d++;
306 	}
307 }
308 
getsub_deinterleaved(uae_u8 * dst,struct cdunit * cdu,struct cdtoc * t,int sector)309 static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector)
310 {
311 	int ret = 0;
312 	uae_sem_wait (&cdu->sub_sem);
313 	if (t->subcode) {
314 		if (t->enctype == ENC_CHD) {
315 #ifdef WITH_CHD
316 			const cdrom_track_info *cti = t->chdtrack;
317 			if (cdrom_read_subcode(cdu->chd_cdf, sector, dst, false))
318 				ret = t->subcode;
319 #endif
320 		} else if (t->subhandle) {
321 			int offset = 0;
322 			int totalsize = SUB_CHANNEL_SIZE;
323 			if (t->skipsize) {
324 				totalsize += t->size;
325 				offset = t->size;
326 			}
327 			zfile_fseek (t->subhandle, (uae_u64)sector * totalsize + t->suboffset + offset, SEEK_SET);
328 			if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0)
329 				ret = t->subcode;
330 		} else {
331 			memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE);
332 			ret = t->subcode;
333 		}
334 	}
335 	if (!ret) {
336 		memset (dst, 0, SUB_CHANNEL_SIZE);
337 		// regenerate Q-subchannel
338 		uae_u8 *s = dst + SUB_ENTRY_SIZE;
339 		s[0] = (t->ctrl << 4) | (t->adr << 0);
340 		s[1] = tobcd (t - &cdu->toc[0] + 1);
341 		s[2] = tobcd (1);
342 		int msf = lsn2msf (sector);
343 		tolongbcd (s + 7, msf);
344 		msf = lsn2msf (sector - t->address - 150);
345 		tolongbcd (s + 3, msf);
346 		ret = 2;
347 	}
348 	if (ret == 1) {
349 		uae_u8 tmp[SUB_CHANNEL_SIZE];
350 		memcpy (tmp, dst, SUB_CHANNEL_SIZE);
351 		sub_to_deinterleaved (tmp, dst);
352 		ret = 2;
353 	}
354 	uae_sem_post (&cdu->sub_sem);
355 	return ret;
356 }
357 
dosub(struct cdunit * cdu,uae_u8 * subbuf)358 static void dosub (struct cdunit *cdu, uae_u8 *subbuf)
359 {
360 	uae_u8 subbuf2[SUB_CHANNEL_SIZE];
361 
362 	if (!cdu->cdda_subfunc)
363 		return;
364 
365 	if (!subbuf) {
366 		memset (subbuf2, 0, sizeof subbuf2);
367 		cdu->cdda_subfunc (subbuf2, 1);
368 		return;
369 	}
370 	sub_to_interleaved (subbuf, subbuf2);
371 	cdu->cdda_subfunc (subbuf2, 1);
372 }
373 
setstate(struct cdunit * cdu,int state)374 static int setstate (struct cdunit *cdu, int state)
375 {
376 	cdu->cdda_play_state = state;
377 	if (cdu->cdda_statusfunc)
378 		return cdu->cdda_statusfunc (cdu->cdda_play_state);
379 	return 0;
380 }
381 
cdda_unpack_func(void * v)382 static void *cdda_unpack_func (void *v)
383 {
384 	cdimage_unpack_thread = 1;
385 	mp3decoder *mp3dec = NULL;
386 
387 	for (;;) {
388 		uae_u32 cduidx = read_comm_pipe_u32_blocking (&unpack_pipe);
389 		if (cdimage_unpack_thread == 0)
390 			break;
391 		uae_u32 tocidx = read_comm_pipe_u32_blocking (&unpack_pipe);
392 		struct cdunit *cdu = &cdunits[cduidx];
393 		struct cdtoc *t = &cdu->toc[tocidx];
394 		if (t->handle) {
395 			// force unpack if handle points to delayed zipped file
396 			uae_s64 pos = zfile_ftell (t->handle);
397 			zfile_fseek (t->handle, -1, SEEK_END);
398 			uae_u8 b;
399 			zfile_fread (&b, 1, 1, t->handle);
400 			zfile_fseek (t->handle, pos, SEEK_SET);
401 			if (!t->data && (t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC)) {
402 				t->data = xcalloc (uae_u8, t->filesize + 2352);
403 				cdimage_unpack_active = 1;
404 				if (t->data) {
405 					if (t->enctype == AUDENC_MP3) {
406 						if (!mp3dec) {
407 							try {
408 								mp3dec = new mp3decoder();
409 							} catch (exception) { };
410 						}
411 						if (mp3dec)
412 							t->data = mp3dec->get (t->handle, t->data, t->filesize);
413 					} else if (t->enctype == AUDENC_FLAC) {
414 						flac_get_data (t);
415 					}
416 				}
417 			}
418 		}
419 		cdimage_unpack_active = 2;
420 	}
421 	delete mp3dec;
422 	cdimage_unpack_thread = -1;
423 	return 0;
424 }
425 
audio_unpack(struct cdunit * cdu,struct cdtoc * t)426 static void audio_unpack (struct cdunit *cdu, struct cdtoc *t)
427 {
428 	// do this even if audio is not compressed, t->handle also could be
429 	// compressed and we want to unpack it in background too
430 	while (cdimage_unpack_active == 1)
431 		sleep_millis(10);
432 	cdimage_unpack_active = 0;
433 	write_comm_pipe_u32 (&unpack_pipe, cdu - &cdunits[0], 0);
434 	write_comm_pipe_u32 (&unpack_pipe, t - &cdu->toc[0], 1);
435 	while (cdimage_unpack_active == 0)
436 		sleep_millis(10);
437 }
438 
439 static volatile int cda_bufon[2];
440 static cda_audio *cda;
441 
next_cd_audio_buffer_callback(int bufnum)442 static void next_cd_audio_buffer_callback(int bufnum)
443 {
444 	uae_sem_wait(&play_sem);
445 	if (bufnum >= 0) {
446 		cda_bufon[bufnum] = 0;
447 		bufnum = 1 - bufnum;
448 		if (cda_bufon[bufnum])
449 			audio_cda_new_buffer((uae_s16*)cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, next_cd_audio_buffer_callback);
450 		else
451 			bufnum = -1;
452 	}
453 	if (bufnum < 0) {
454 		audio_cda_new_buffer(NULL, 0, -1, NULL);
455 	}
456 	uae_sem_post(&play_sem);
457 }
458 
cdda_play_func(void * v)459 static void *cdda_play_func (void *v)
460 {
461 	int cdda_pos;
462 	int bufnum;
463 	int oldplay;
464 	int idleframes = 0;
465 	int silentframes = 0;
466 	bool foundsub;
467 	struct cdunit *cdu = (struct cdunit*)v;
468 	int oldtrack = -1;
469 	int mode = currprefs.sound_cdaudio;
470 
471 	cdu->thread_active = true;
472 
473 	while (cdu->cdda_play == 0)
474 		sleep_millis(10);
475 	oldplay = -1;
476 
477 	cda_bufon[0] = cda_bufon[1] = 0;
478 	bufnum = 0;
479 
480 	cda = new cda_audio (CDDA_BUFFERS, 2352, 44100);
481 
482 	while (cdu->cdda_play > 0) {
483 
484 		if (oldplay != cdu->cdda_play) {
485 			struct cdtoc *t;
486 			int sector, diff;
487 #ifdef HAVE_SYS_TIMEB_H
488 			struct _timeb tb1, tb2;
489 #else
490 #warning Missing timing functions
491 #endif
492 
493 			idleframes = 0;
494 			silentframes = 0;
495 			foundsub = false;
496 #ifdef HAVE_SYS_TIMEB_H
497 			_ftime (&tb1);
498 #endif
499 			cdda_pos = cdu->cdda_start;
500 			oldplay = cdu->cdda_play;
501 			sector = cdu->cd_last_pos = cdda_pos;
502 			t = findtoc (cdu, &sector, false);
503 			if (!t) {
504 				sector = cdu->cd_last_pos = cdda_pos + 2 * 75;
505 				t = findtoc (cdu, &sector, false);
506 				if (!t) {
507 					write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
508 					setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
509 				} else {
510 					audio_unpack (cdu, t);
511 				}
512 			} else {
513 				write_log (_T("IMAGE CDDA: playing from %d to %d, track %d ('%s', offset %lld, secoffset %d (%d))\n"),
514 					cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector, t->index1);
515 				oldtrack = t->track;
516 				audio_unpack (cdu, t);
517 			}
518 			idleframes = cdu->cdda_delay_frames;
519 			while (cdu->cdda_paused && cdu->cdda_play > 0) {
520 				sleep_millis(10);
521 				idleframes = -1;
522 			}
523 
524 			if (cdu->cdda_scan == 0) {
525 				// find possible P-subchannel=1 and fudge starting point so that
526 				// buggy CD32/CDTV software CD+G handling does not miss any frames
527 				bool seenindex = false;
528 				for (sector = cdda_pos - 200; sector < cdda_pos; sector++) {
529 					int sec = sector;
530 					t = findtoc (cdu, &sec, false);
531 					if (t) {
532 						uae_u8 subbuf[SUB_CHANNEL_SIZE];
533 						getsub_deinterleaved (subbuf, cdu, t, sector);
534 						if (seenindex) {
535 							for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) {
536 								if (subbuf[i]) { // non-zero R-W subchannels
537 									int diff = cdda_pos - sector + 2;
538 									write_log (_T("-> CD+G start pos fudge -> %d (%d)\n"), sector, -diff);
539 									idleframes -= diff;
540 									cdda_pos = sector;
541 									break;
542 								}
543 							}
544 						} else if (subbuf[0] == 0xff) { // P == 1?
545 							seenindex = true;
546 						}
547 					}
548 				}
549 			}
550 			cdda_pos -= idleframes;
551 
552 #ifdef HAVE_SYS_TIMEB_H
553 			_ftime (&tb2);
554 			diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
555 			diff -= cdu->cdda_delay;
556 #else
557 			diff = 0;
558 #endif
559 			if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0)
560 				sleep_millis(-diff);
561 			setstate (cdu, AUDIO_STATUS_IN_PROGRESS);
562 
563 			sector = cdda_pos;
564 			struct cdtoc *t1 = findtoc (cdu, &sector, false);
565 			int tsector = cdda_pos + 2 * 75;
566 			struct cdtoc *t2 = findtoc (cdu, &tsector, false);
567 			if (t1 != t2) {
568 				for (sector = cdda_pos; sector < cdda_pos + 2 * 75; sector++) {
569 					int sec = sector;
570 					t = findtoc (cdu, &sec, false);
571 					if (t == t2)
572 						break;
573 					silentframes++;
574 				}
575 			}
576 		}
577 
578 		if (mode) {
579 			while (cda_bufon[bufnum] && cdu->cdda_play > 0)
580 				sleep_millis(10);
581 		} else {
582 			cda->wait(bufnum);
583 		}
584 
585 		cda_bufon[bufnum] = 0;
586 		if (cdu->cdda_play <= 0)
587 			goto end;
588 
589 		if (idleframes <= 0 && cdda_pos >= cdu->cdda_start && !isaudiotrack (&cdu->di.toc, cdda_pos)) {
590 			setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
591 			write_log (_T("IMAGE CDDA: attempted to play data track %d\n"), cdda_pos);
592 			goto end; // data track?
593 		}
594 
595 		if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) {
596 			struct cdtoc *t;
597 			int sector, cnt;
598 			int dofinish = 0;
599 
600 			gui_flicker_led (LED_CD, cdu->di.unitnum - 1, LED_CD_AUDIO);
601 
602 			memset (cda->buffers[bufnum], 0, CDDA_BUFFERS * 2352);
603 
604 			for (cnt = 0; cnt < CDDA_BUFFERS && cdu->cdda_play > 0; cnt++) {
605 				uae_u8 *dst = cda->buffers[bufnum] + cnt * 2352;
606 				uae_u8 subbuf[SUB_CHANNEL_SIZE];
607 				sector = cdda_pos;
608 
609 				memset (subbuf, 0, SUB_CHANNEL_SIZE);
610 
611 				t = findtoc (cdu, &sector, false);
612 				if (t) {
613 					if (t->track != oldtrack) {
614 						oldtrack = t->track;
615 						write_log (_T("IMAGE CDDA: track %d ('%s', offset %lld, secoffset %d (%d))\n"),
616 							t->track, t->fname, t->offset, sector, t->index1);
617 						audio_unpack (cdu, t);
618 					}
619 					if (!(t->ctrl & 4)) {
620 						if (t->enctype == ENC_CHD) {
621 #ifdef WITH_CHD
622 							do_read (cdu, t, dst, sector, 0, t->size, true);
623 							for (int i = 0; i < 2352; i+=2) {
624 								uae_u8 p;
625 								p = dst[i + 0];
626 								dst[i + 0] = dst[i + 1];
627 								dst[i +1] = p;
628 							}
629 #endif
630 						} else if (t->handle) {
631 							int totalsize = t->size + t->skipsize;
632 							int offset = t->offset;
633 							if (offset >= 0) {
634 								if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
635 									if (t->filesize >= sector * totalsize + offset + t->size)
636 										memcpy (dst, t->data + sector * totalsize + offset, t->size);
637 								} else if (t->enctype == AUDENC_PCM) {
638 									if (sector * totalsize + offset + totalsize < t->filesize) {
639 										zfile_fseek (t->handle, (uae_u64)sector * totalsize + offset, SEEK_SET);
640 										zfile_fread (dst, t->size, 1, t->handle);
641 									}
642 								}
643 							}
644 						}
645 					}
646 					getsub_deinterleaved (subbuf, cdu, t, cdda_pos);
647 				}
648 
649 				if (idleframes > 0 || silentframes > 0) {
650 					if (idleframes > 0) {
651 						idleframes--;
652 						memset (subbuf, 0, SUB_CHANNEL_SIZE);
653 					}
654 					if (silentframes > 0)
655 						silentframes--;
656 					memset (dst, 0, 2352);
657 				}
658 
659 				if (cdda_pos < cdu->cdda_start && cdu->cdda_scan == 0)
660 					memset (dst, 0, 2352);
661 
662 				dosub (cdu, subbuf);
663 
664 				if (cdu->cdda_scan) {
665 					cdda_pos += cdu->cdda_scan;
666 					if (cdda_pos < 0)
667 						cdda_pos = 0;
668 				} else  {
669 					cdda_pos++;
670 				}
671 
672 				if (cdda_pos - CDDA_BUFFERS < cdu->cdda_end && cdda_pos >= cdu->cdda_end)
673 					dofinish = 1;
674 
675 			}
676 
677 			if (idleframes <= 0)
678 				cdu->cd_last_pos = cdda_pos;
679 
680 			if (mode) {
681 				if (cda_bufon[0] == 0 && cda_bufon[1] == 0) {
682 					cda_bufon[bufnum] = 1;
683 					next_cd_audio_buffer_callback(1 - bufnum);
684 				}
685 				audio_cda_volume(cdu->cdda_volume[0], cdu->cdda_volume[1]);
686 				cda_bufon[bufnum] = 1;
687 			} else {
688 				cda_bufon[bufnum] = 1;
689 				cda->setvolume (cdu->cdda_volume[0], cdu->cdda_volume[1]);
690 				if (!cda->play (bufnum)) {
691 					if (cdu->cdda_play > 0)
692 						setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
693 					goto end;
694 				}
695 			}
696 
697 			if (dofinish) {
698 				if (cdu->cdda_play >= 0)
699 					setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE);
700 				cdu->cdda_play = -1;
701 				cdda_pos = cdu->cdda_end + 1;
702 			}
703 
704 		}
705 
706 		if (cda_bufon[0] == 0 && cda_bufon[1] == 0) {
707 			while (cdu->cdda_paused && cdu->cdda_play == oldplay)
708 				sleep_millis(10);
709 		}
710 
711 		bufnum = 1 - bufnum;
712 	}
713 
714 end:
715 	if (mode) {
716 		next_cd_audio_buffer_callback(-1);
717 	} else {
718 		cda->wait (0);
719 		cda->wait (1);
720 	}
721 
722 	while (cdimage_unpack_active == 1)
723 		sleep_millis(10);
724 
725 	delete cda;
726 
727 	cdu->cdda_play = 0;
728 	write_log (_T("IMAGE CDDA: thread killed\n"));
729 	cdu->thread_active = false;
730 	return NULL;
731 }
732 
733 
cdda_stop(struct cdunit * cdu)734 static void cdda_stop (struct cdunit *cdu)
735 {
736 	if (cdu->cdda_play != 0) {
737 		cdu->cdda_play = -1;
738 		while (cdu->cdda_play && cdu->thread_active) {
739 			sleep_millis(10);
740 		}
741 		cdu->cdda_play = 0;
742 	}
743 	cdu->cdda_paused = 0;
744 	cdu->cdda_play_state = 0;
745 }
746 
747 
command_pause(int unitnum,int paused)748 static int command_pause (int unitnum, int paused)
749 {
750 	struct cdunit *cdu = unitisopen (unitnum);
751 	if (!cdu)
752 		return -1;
753 	int old = cdu->cdda_paused;
754 	if ((paused && cdu->cdda_play) || !paused)
755 		cdu->cdda_paused = paused;
756 	return old;
757 }
758 
command_stop(int unitnum)759 static int command_stop (int unitnum)
760 {
761 	struct cdunit *cdu = unitisopen (unitnum);
762 	if (!cdu)
763 		return 0;
764 	cdda_stop (cdu);
765 	return 1;
766 }
767 
command_play(int unitnum,int startlsn,int endlsn,int scan,play_status_callback statusfunc,play_subchannel_callback subfunc)768 static int command_play (int unitnum, int startlsn, int endlsn, int scan, play_status_callback statusfunc, play_subchannel_callback subfunc)
769 {
770 	struct cdunit *cdu = unitisopen (unitnum);
771 	if (!cdu)
772 		return 0;
773 	if (cdu->cdda_play) {
774 		cdu->cdda_play = -1;
775 		while (cdu->thread_active)
776 			Sleep (10);
777 		cdu->cdda_play = 0;
778 	}
779 	cdu->cd_last_pos = startlsn;
780 	cdu->cdda_start = startlsn;
781 	cdu->cdda_end = endlsn;
782 	cdu->cdda_subfunc = subfunc;
783 	cdu->cdda_statusfunc = statusfunc;
784 	cdu->cdda_scan = scan > 0 ? 10 : (scan < 0 ? 10 : 0);
785 	cdu->cdda_delay = setstate (cdu, -1);
786 	cdu->cdda_delay_frames = setstate (cdu, -2);
787 	setstate (cdu, AUDIO_STATUS_NOT_SUPPORTED);
788 	if (!isaudiotrack (&cdu->di.toc, startlsn)) {
789 		setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
790 		return 0;
791 	}
792 	if (!cdu->thread_active) {
793 		uae_start_thread (_T("cdimage_cdda_play"), cdda_play_func, cdu, NULL);
794 		while (!cdu->thread_active)
795 			Sleep (10);
796 	}
797 	cdu->cdda_play++;
798 	return 1;
799 }
800 
command_qcode(int unitnum,uae_u8 * buf,int sector)801 static int command_qcode (int unitnum, uae_u8 *buf, int sector)
802 {
803 	struct cdunit *cdu = unitisopen (unitnum);
804 	if (!cdu)
805 		return 0;
806 
807 	uae_u8 subbuf[SUB_CHANNEL_SIZE];
808 	uae_u8 *p;
809 	int trk;
810 	int pos;
811 	int status;
812 
813 	memset (buf, 0, SUBQ_SIZE);
814 	p = buf;
815 
816 	status = cdu->cdda_play_state;
817 	if (cdu->cdda_play > 0 && cdu->cdda_paused)
818 		status = AUDIO_STATUS_PAUSED;
819 
820 	if (sector < 0)
821 		pos = cdu->cd_last_pos;
822 	else
823 		pos = sector;
824 
825 	p[1] = status;
826 	p[3] = 12;
827 
828 	p = buf + 4;
829 
830 	struct cdtoc *td = NULL;
831 	for (trk = 0; trk <= cdu->tracks; trk++) {
832 		td = &cdu->toc[trk];
833 		if (pos < td->address) {
834 			if (trk > 0)
835 				td--;
836 			break;
837 		}
838 		if (pos >= td->address && pos < td[1].address)
839 			break;
840 	}
841 	if (!td)
842 		return 0;
843 	getsub_deinterleaved (subbuf, cdu, td, pos);
844 	memcpy (p, subbuf + 12, 12);
845 //	write_log (_T("%6d %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x\n"),
846 //		pos, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]);
847 	return 1;
848 }
849 
command_volume(int unitnum,uae_u16 volume_left,uae_u16 volume_right)850 static uae_u32 command_volume (int unitnum, uae_u16 volume_left, uae_u16 volume_right)
851 {
852 	struct cdunit *cdu = unitisopen (unitnum);
853 	if (!cdu)
854 		return -1;
855 	uae_u32 old = (cdu->cdda_volume[1] << 16) | (cdu->cdda_volume[0] << 0);
856 	cdu->cdda_volume[0] = volume_left;
857 	cdu->cdda_volume[1] = volume_right;
858 	return old;
859 }
860 
861 extern void encode_l2 (uae_u8 *p, int address);
862 
command_rawread(int unitnum,uae_u8 * data,int sector,int size,int sectorsize,uae_u32 extra)863 static int command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u32 extra)
864 {
865 	int ret = 0;
866 	struct cdunit *cdu = unitisopen (unitnum);
867 	if (!cdu)
868 		return 0;
869 	int asector = sector;
870 	struct cdtoc *t = findtoc (cdu, &sector, true);
871 	int ssize;
872 
873 	if (!t)
874 		goto end;
875 
876 	ssize = t->size + t->skipsize;
877 	cdda_stop (cdu);
878 	if (sectorsize > 0) {
879 		if (sectorsize == 2352 && t->size == 2336) {
880 			// 2336 -> 2352
881 			while (size-- > 0) {
882 				int address = asector + 150;
883 				data[0] = 0x00;
884 				memset(data + 1, 0xff, 11);
885 				data[12] = tobcd((uae_u8)(address / (60 * 75)));
886 				data[13] = tobcd((uae_u8)((address / 75) % 60));
887 				data[14] = tobcd((uae_u8)(address % 75));
888 				data[15] = 2; /* MODE2 */
889 				do_read(cdu, t, data + 16, sector, 0, t->size, false);
890 				sector++;
891 				asector++;
892 				data += sectorsize;
893 				ret += sectorsize;
894 			}
895 		} else if (sectorsize == 2352 && t->size == 2048) {
896 			// 2048 -> 2352
897 			while (size-- > 0) {
898 				memset (data, 0, 16);
899 				do_read (cdu, t, data + 16, sector, 0, 2048, false);
900 				encode_l2 (data, sector + 150);
901 				sector++;
902 				asector++;
903 				data += sectorsize;
904 				ret += sectorsize;
905 			}
906 		} else if (sectorsize == 2048 && t->size == 2352) {
907 			// 2352 -> 2048
908 			while (size-- > 0) {
909 				uae_u8 b = 0;
910 				do_read (cdu, t, &b, sector, 15, 1, false);
911 				do_read (cdu, t, data, sector, b == 2 ? 24 : 16, sectorsize, false);
912 				sector++;
913 				asector++;
914 				data += sectorsize;
915 				ret += sectorsize;
916 			}
917 		} else if (sectorsize == 2336 && t->size == 2352) {
918 			// 2352 -> 2336
919 			while (size-- > 0) {
920 				uae_u8 b = 0;
921 				do_read (cdu, t, &b, sector, 15, 1, false);
922 				if (b != 2 && b != 0) // MODE0 or MODE2 only allowed
923 					return 0;
924 				do_read (cdu, t, data, sector, 16, sectorsize, false);
925 				sector++;
926 				asector++;
927 				data += sectorsize;
928 				ret += sectorsize;
929 			}
930 		} else if (sectorsize == t->size) {
931 			// no change
932 			while (size -- > 0) {
933 				do_read (cdu, t, data, sector, 0, sectorsize, false);
934 				sector++;
935 				asector++;
936 				data += sectorsize;
937 				ret++;
938 			}
939 		}
940 		cdu->cd_last_pos = asector;
941 
942 	} else {
943 
944 		uae_u8 sectortype = extra >> 16;
945 		uae_u8 cmd9 = extra >> 8;
946 		int sync = (cmd9 >> 7) & 1;
947 		int headercodes = (cmd9 >> 5) & 3;
948 		int userdata = (cmd9 >> 4) & 1;
949 		int edcecc = (cmd9 >> 3) & 1;
950 		int errorfield = (cmd9 >> 1) & 3;
951 		uae_u8 subs = extra & 7;
952 		if (subs != 0 && subs != 1 && subs != 2 && subs != 4) {
953 			ret = -1;
954 			goto end;
955 		}
956 
957 		if (sectortype != 0 && sectortype != 1) {
958 			ret = -2;
959 			goto end;
960 		}
961 		if (t->size != 2352) {
962 			ret = -1;
963 			goto end;
964 		}
965 		for (int i = 0; i < size; i++) {
966 			do_read (cdu, t, data, sector, 0, t->size, true);
967 			uae_u8 *p = data + t->size;
968 			if (subs) {
969 				uae_u8 subdata[SUB_CHANNEL_SIZE];
970 				getsub_deinterleaved (subdata, cdu, t, sector);
971 				if (subs == 4) { // all, de-interleaved
972 					memcpy (p, subdata, SUB_CHANNEL_SIZE);
973 					p += SUB_CHANNEL_SIZE;
974 				} else if (subs == 2) { // q-only
975 					memcpy (p, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE);
976 					p += SUB_ENTRY_SIZE;
977 				} else if (subs == 1) { // all, interleaved
978 					sub_to_interleaved (subdata, p);
979 					p += SUB_CHANNEL_SIZE;
980 				}
981 			}
982 			ret += p - data;
983 			data = p;
984 			sector++;
985 		}
986 	}
987 end:
988 	return ret;
989 }
990 
991 // return standard 2048 byte sectors only
command_read(int unitnum,uae_u8 * data,int sector,int numsectors)992 static int command_read (int unitnum, uae_u8 *data, int sector, int numsectors)
993 {
994 	struct cdunit *cdu = unitisopen (unitnum);
995 	if (!cdu)
996 		return 0;
997 	struct cdtoc *t = findtoc (cdu, &sector, true);
998 	if (!t)
999 		return 0;
1000 	cdda_stop (cdu);
1001 	if (t->size == 2048) {
1002 		while (numsectors-- > 0) {
1003 			do_read (cdu, t, data, sector, 0, 2048, false);
1004 			data += 2048;
1005 			sector++;
1006 		}
1007 	} else {
1008 		while (numsectors-- > 0) {
1009 			if (t->size == 2352) {
1010 				uae_u8 b = 0;
1011 				do_read (cdu, t, &b, sector, 15, 1, false);
1012 				// 2 = MODE2
1013 				do_read (cdu, t, data, sector, b == 2 ? 24 : 16, 2048, false);
1014 			} else {
1015 				// 2336
1016 				do_read (cdu, t, data, sector, 8, 2048, false);
1017 			}
1018 			data += 2048;
1019 			sector++;
1020 		}
1021 	}
1022 	cdu->cd_last_pos = sector;
1023 	return 1;
1024 }
1025 
command_toc(int unitnum,struct cd_toc_head * th)1026 static int command_toc (int unitnum, struct cd_toc_head *th)
1027 {
1028 	struct cdunit *cdu = unitisopen (unitnum);
1029 	if (!cdu)
1030 		return 0;
1031 
1032 	int i;
1033 
1034 	memset (&cdu->di.toc, 0, sizeof (struct cd_toc_head));
1035 	if (!cdu->tracks)
1036 		return 0;
1037 
1038 	memset (th, 0, sizeof (struct cd_toc_head));
1039 	struct cd_toc *toc = &th->toc[0];
1040 	th->first_track = 1;
1041 	th->last_track = cdu->tracks;
1042 	th->points = cdu->tracks + 3;
1043 	th->tracks = cdu->tracks;
1044 	th->firstaddress = 0;
1045 	th->lastaddress = cdu->toc[cdu->tracks].address;
1046 
1047 	toc->adr = 1;
1048 	toc->point = 0xa0;
1049 	toc->track = th->first_track;
1050 	toc++;
1051 
1052 	th->first_track_offset = 1;
1053 	for (i = 0; i < cdu->tracks; i++) {
1054 		toc->adr = cdu->toc[i].adr;
1055 		toc->control = cdu->toc[i].ctrl;
1056 		toc->track = i + 1;
1057 		toc->point = i + 1;
1058 		toc->paddress = cdu->toc[i].address;
1059 		toc++;
1060 	}
1061 
1062 	th->last_track_offset = cdu->tracks;
1063 	toc->adr = 1;
1064 	toc->point = 0xa1;
1065 	toc->track = th->last_track;
1066 	toc->paddress = th->lastaddress;
1067 	toc++;
1068 
1069 	toc->adr = 1;
1070 	toc->point = 0xa2;
1071 	toc->paddress = th->lastaddress;
1072 	toc++;
1073 
1074 	memcpy (&cdu->di.toc, th, sizeof (struct cd_toc_head));
1075 	return 1;
1076 }
1077 
skipspace(TCHAR ** s)1078 static void skipspace (TCHAR **s)
1079 {
1080 	while (_istspace (**s))
1081 		(*s)++;
1082 }
skipnspace(TCHAR ** s)1083 static void skipnspace (TCHAR **s)
1084 {
1085 	while (!_istspace (**s))
1086 		(*s)++;
1087 }
1088 
nextstring(TCHAR ** sp)1089 static TCHAR *nextstring (TCHAR **sp)
1090 {
1091 	TCHAR *s;
1092 	TCHAR *out = NULL;
1093 
1094 	skipspace (sp);
1095 	s = *sp;
1096 	if (*s == '\"') {
1097 		s++;
1098 		out = s;
1099 		while (*s && *s != '\"')
1100 			s++;
1101 		*s++ = 0;
1102 	} else if (*s) {
1103 		out = s;
1104 		skipnspace (&s);
1105 		*s++ = 0;
1106 	}
1107 	*sp = s;
1108 	return out;
1109 }
1110 
readval(const TCHAR * s)1111 static int readval (const TCHAR *s)
1112 {
1113 	int base = 10;
1114 	TCHAR *endptr;
1115 	if (s[0] == '0' && _totupper (s[1]) == 'X')
1116 		s += 2, base = 16;
1117 	return _tcstol (s, &endptr, base);
1118 }
1119 
1120 #define MEDIA_DESCRIPTOR "MEDIA DESCRIPTOR"
1121 
1122 /* MDS spec structures from cdemu */
1123 
1124 #define MDS_MEDIUM_CD           0x00 /* CD-ROM */
1125 #define MDS_MEDIUM_CD_R         0x01 /* CD-R */
1126 #define MDS_MEDIUM_CD_RW        0x02 /* CD-RW */
1127 #define MDS_MEDIUM_DVD          0x10 /* DVD-ROM */
1128 #define MDS_MEDIUM_DVD_MINUS_R  0x12 /* DVD-R */
1129 
1130 #define MDS_TRACKMODE_UNKNOWN       0x00
1131 #define MDS_TRACKMODE_AUDIO         0xA9 /* sector size = 2352 */
1132 #define MDS_TRACKMODE_MODE1         0xAA /* sector size = 2048 */
1133 #define MDS_TRACKMODE_MODE2         0xAB /* sector size = 2336 */
1134 #define MDS_TRACKMODE_MODE2_FORM1   0xAC /* sector size = 2048 */
1135 #define MDS_TRACKMODE_MODE2_FORM2   0xAD /* sector size = 2324 (+4) */
1136 
1137 #define MDS_SUBCHAN_NONE            0x00 /* no subchannel */
1138 #define MDS_SUBCHAN_PW_INTERLEAVED  0x08 /* 96-byte PW subchannel, interleaved */
1139 
1140 #define MDS_POINT_TRACK_FIRST   0xA0 /* info about first track */
1141 #define MDS_POINT_TRACK_LAST    0xA1 /* info about last track  */
1142 #define MDS_POINT_TRACK_LEADOUT 0xA2 /* info about lead-out    */
1143 
1144 #pragma pack(1)
1145 
1146 typedef struct {
1147     uae_u8 signature[16]; /* "MEDIA DESCRIPTOR" */
1148     uae_u8 version[2]; /* Version ? */
1149     uae_u16 medium_type; /* Medium type */
1150     uae_u16 num_sessions; /* Number of sessions */
1151     uae_u16 __dummy1__[2]; /* Wish I knew... */
1152     uae_u16 bca_len; /* Length of BCA data (DVD-ROM) */
1153     uae_u32 __dummy2__[2];
1154     uae_u32 bca_data_offset; /* Offset to BCA data (DVD-ROM) */
1155     uae_u32 __dummy3__[6]; /* Probably more offsets */
1156     uae_u32 disc_structures_offset; /* Offset to disc structures */
1157     uae_u32 __dummy4__[3]; /* Probably more offsets */
1158     uae_u32 sessions_blocks_offset; /* Offset to session blocks */
1159     uae_u32 dpm_blocks_offset; /* offset to DPM data blocks */
1160 } MDS_Header; /* length: 88 bytes */
1161 
1162 typedef struct {
1163     uae_s32 session_start; /* Session's start address */
1164     uae_s32 session_end; /* Session's end address */
1165     uae_u16 session_number; /* (Unknown) */
1166     uae_u8 num_all_blocks; /* Number of all data blocks. */
1167     uae_u8 num_nontrack_blocks; /* Number of lead-in data blocks */
1168     uae_u16 first_track; /* Total number of sessions in image? */
1169     uae_u16 last_track; /* Number of regular track data blocks. */
1170     uae_u32 __dummy2__; /* (unknown) */
1171     uae_u32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */
1172 } MDS_SessionBlock; /* length: 24 bytes */
1173 
1174 typedef struct {
1175     uae_u8 mode; /* Track mode */
1176     uae_u8 subchannel; /* Subchannel mode */
1177     uae_u8 adr_ctl; /* Adr/Ctl */
1178     uae_u8 __dummy2__; /* Track flags? */
1179     uae_u8 point; /* Track number. (>0x99 is lead-in track) */
1180 
1181     uae_u32 __dummy3__;
1182     uae_u8 min; /* Min */
1183     uae_u8 sec; /* Sec */
1184     uae_u8 frame; /* Frame */
1185     uae_u32 extra_offset; /* Start offset of this track's extra block. */
1186     uae_u16 sector_size; /* Sector size. */
1187 
1188     uae_u8 __dummy4__[18];
1189     uae_u32 start_sector; /* Track start sector (PLBA). */
1190     uae_u64 start_offset; /* Track start offset. */
1191     uae_u8 session; /* Session or index? */
1192     uae_u8 __dummy5__[3];
1193     uae_u32 footer_offset; /* Start offset of footer. */
1194     uae_u8 __dummy6__[24];
1195 } MDS_TrackBlock; /* length: 80 bytes */
1196 
1197 typedef struct {
1198     uae_u32 pregap; /* Number of sectors in pregap. */
1199     uae_u32 length; /* Number of sectors in track. */
1200 } MDS_TrackExtraBlock; /* length: 8 bytes */
1201 
1202 typedef struct {
1203     uae_u32 filename_offset; /* Start offset of image filename. */
1204     uae_u32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */
1205     uae_u32 __dummy1__;
1206     uae_u32 __dummy2__;
1207 } MDS_Footer; /* length: 16 bytes */
1208 
1209 #pragma pack()
1210 
parsemds(struct cdunit * cdu,struct zfile * zmds,const TCHAR * img)1211 static int parsemds (struct cdunit *cdu, struct zfile *zmds, const TCHAR *img)
1212 {
1213 	MDS_Header *head;
1214 	struct cdtoc *t;
1215 	uae_u8 *mds = NULL;
1216 	uae_u64 size;
1217 	MDS_SessionBlock *sb;
1218 
1219 	write_log (_T("MDS TOC: '%s'\n"), img);
1220 	size = zfile_size (zmds);
1221 	mds = xmalloc (uae_u8, size);
1222 	if (!mds)
1223 		goto end;
1224 	if (zfile_fread (mds, size, 1, zmds) != 1)
1225 		goto end;
1226 
1227 	head = (MDS_Header*)mds;
1228 	if (!memcmp (&head, MEDIA_DESCRIPTOR, strlen (MEDIA_DESCRIPTOR)))
1229 		goto end;
1230 	if (head->version[0] != 1) {
1231 		write_log (_T("unsupported MDS version %d, only v.1 supported\n"), head->version[0]);
1232 		goto end;
1233 	}
1234 
1235 	sb = (MDS_SessionBlock*)(mds + head->sessions_blocks_offset);
1236 	cdu->tracks = sb->last_track - sb->first_track + 1;
1237 	for (int i = 0; i < sb->num_all_blocks; i++) {
1238 		MDS_TrackBlock *tb = (MDS_TrackBlock*)(mds + sb->tracks_blocks_offset + i * sizeof (MDS_TrackBlock));
1239 		int point = tb->point;
1240 		int tracknum = -1;
1241 		if (point == 0xa2)
1242 			tracknum = cdu->tracks;
1243 		else if (point >= 1 && point <= 99)
1244 			tracknum = point - 1;
1245 		if (tracknum >= 0) {
1246 			MDS_Footer *footer = tb->footer_offset == 0 ? NULL : (MDS_Footer*)(mds + tb->footer_offset);
1247 			MDS_TrackExtraBlock *teb = tb->extra_offset == 0 ? NULL : (MDS_TrackExtraBlock*)(mds + tb->extra_offset);
1248 			t = &cdu->toc[tracknum];
1249 			t->adr = tb->adr_ctl >> 4;
1250 			t->ctrl = tb->adr_ctl & 15;
1251 			if (point == 0xa2)
1252 				t->address = sb->session_end;
1253 			else
1254 				t->address = tb->start_sector;
1255 			t->track = point;
1256 			t->offset = tb->start_offset;
1257 			t->size = tb->sector_size;
1258 
1259 			if (point >= 100)
1260 				continue;
1261 
1262 			if (footer) {
1263 				TCHAR *fname = NULL;
1264 				if (footer->widechar_filename == 0)
1265 					fname = au ((char*)(mds + footer->filename_offset));
1266 				else
1267 					fname = my_strdup ((TCHAR*)(mds + footer->filename_offset));
1268 				if (fname[0] == '*' && fname[1] == '.') {
1269 					TCHAR newname[MAX_DPATH];
1270 					_tcscpy (newname, img);
1271 					TCHAR *ext = _tcsrchr (newname, '.');
1272 					if (ext)
1273 						_tcscpy (ext, fname + 1);
1274 					xfree (fname);
1275 					fname = my_strdup (newname);
1276 				}
1277 
1278 				t->handle = zfile_fopen (fname, _T("rb"), ZFD_NORMAL);
1279 				t->fname = my_strdup (fname);
1280 				if (t->handle)
1281 					t->filesize = zfile_size (t->handle);
1282 			}
1283 
1284 			if (tb->subchannel && t->handle) {
1285 				t->suboffset = t->size;
1286 				t->subcode = 1; // interleaved
1287 				t->subhandle = zfile_dup (t->handle);
1288 				t->skipsize = SUB_CHANNEL_SIZE;
1289 				t->size -= SUB_CHANNEL_SIZE;
1290 			}
1291 			if ((t->ctrl & 0x0c) != 4)
1292 				t->enctype = AUDENC_PCM;
1293 		}
1294 	}
1295 
1296 end:
1297 	xfree (mds);
1298 
1299 	return cdu->tracks;
1300 }
1301 
1302 #ifdef WITH_CHD
parsechd(struct cdunit * cdu,struct zfile * zcue,const TCHAR * img)1303 static int parsechd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
1304 {
1305 	chd_error err;
1306 	struct cdrom_file *cdf;
1307 	struct zfile *f = zfile_dup (zcue);
1308 	if (!f)
1309 		return 0;
1310 	chd_file *cf = new chd_file();
1311 	err = cf->open(*f, false, NULL);
1312 	if (err != CHDERR_NONE) {
1313 		write_log (_T("CHD '%s' err=%d\n"), zfile_getname (zcue), err);
1314 		zfile_fclose (f);
1315 		return 0;
1316 	}
1317 	if (!(cdf = cdrom_open (cf))) {
1318 		write_log (_T("Couldn't open CHD '%s' as CD\n"), zfile_getname (zcue));
1319 		cf->close ();
1320 		zfile_fclose (f);
1321 		return 0;
1322 	}
1323 	cdu->chd_f = cf;
1324 	cdu->chd_cdf = cdf;
1325 
1326 	const cdrom_toc *stoc = cdrom_get_toc (cdf);
1327 	cdu->tracks = stoc->numtrks;
1328 	uae_u32 hunkcnt = cf->hunk_count ();
1329 	uae_u32 hunksize = cf->hunk_bytes ();
1330 	uae_u32 cbytes;
1331 	chd_codec_type compr;
1332 
1333 	for (int i = 0; i <cdu->tracks; i++) {
1334 		int size;
1335 		const cdrom_track_info *strack = &stoc->tracks[i];
1336 		struct cdtoc *dtrack = &cdu->toc[i];
1337 		dtrack->address = strack->physframeofs;
1338 		dtrack->offset = strack->chdframeofs;
1339 		dtrack->adr = cdrom_get_adr_control (cdf, i) >> 4;
1340 		dtrack->ctrl = cdrom_get_adr_control (cdf, i) & 15;
1341 		switch (strack->trktype)
1342 		{
1343 			case CD_TRACK_MODE1:
1344 			case CD_TRACK_MODE2_FORM1:
1345 				size = 2048;
1346 			break;
1347 			case CD_TRACK_MODE1_RAW:
1348 			case CD_TRACK_MODE2_RAW:
1349 			case CD_TRACK_AUDIO:
1350 			default:
1351 				size = 2352;
1352 			break;
1353 			case CD_TRACK_MODE2:
1354 			case CD_TRACK_MODE2_FORM_MIX:
1355 				size = 2336;
1356 			break;
1357 			case CD_TRACK_MODE2_FORM2:
1358 				size = 2324;
1359 			break;
1360 		}
1361 		dtrack->suboffset = size;
1362 		dtrack->subcode = strack->subtype == CD_SUB_NONE ? 0 : strack->subtype == CD_SUB_RAW ? 1 : 2;
1363 		dtrack->chdtrack = strack;
1364 		dtrack->size = size;
1365 		dtrack->enctype = ENC_CHD;
1366 		dtrack->fname = my_strdup (zfile_getname (zcue));
1367 		dtrack->filesize = cf->logical_bytes ();
1368 		dtrack->track = i + 1;
1369 		dtrack[1].address = dtrack->address + strack->frames;
1370 		if (cf->hunk_info(dtrack->offset * CD_FRAME_SIZE / hunksize, compr, cbytes) == CHDERR_NONE) {
1371 			TCHAR tmp[100];
1372 			uae_u32 c = (uae_u32)compr;
1373 			for (int j = 0; j < 4; j++) {
1374 				uae_u8 b = c >> ((3 - j) * 8);
1375 				if (c < 10) {
1376 					b += '0';
1377 				}
1378 				if (b < ' ' || b >= 127)
1379 						b = '.';
1380 				tmp[j] = b;
1381 			}
1382 			tmp[4] = 0;
1383 			dtrack->extrainfo = my_strdup (tmp);
1384 		}
1385 
1386 	}
1387 	return cdu->tracks;
1388 }
1389 #endif
1390 
parseccd(struct cdunit * cdu,struct zfile * zcue,const TCHAR * img)1391 static int parseccd (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
1392 {
1393 	int mode;
1394 	int num, tracknum, trackmode;
1395 	int adr, control, lba;
1396 	bool gotlba;
1397 	struct cdtoc *t;
1398 	struct zfile *zimg, *zsub;
1399 	TCHAR fname[MAX_DPATH];
1400 
1401 	write_log (_T("CCD TOC: '%s'\n"), img);
1402 	_tcscpy (fname, zfile_getname(zcue));
1403 	TCHAR *ext = _tcsrchr (fname, '.');
1404 	if (ext)
1405 		*ext = 0;
1406 	_tcscat (fname, _T(".img"));
1407 	zimg = zfile_fopen (fname, _T("rb"), ZFD_NORMAL);
1408 	if (!zimg) {
1409 		write_log (_T("CCD: can't open '%s'\n"), fname);
1410 		return 0;
1411 	}
1412 	ext = _tcsrchr (fname, '.');
1413 	if (ext)
1414 		*ext = 0;
1415 	_tcscat (fname, _T(".sub"));
1416 	zsub = zfile_fopen (fname, _T("rb"), ZFD_NORMAL);
1417 	if (zsub)
1418 		write_log (_T("CCD: '%s' detected\n"), fname);
1419 
1420 	num = -1;
1421 	mode = -1;
1422 	for (;;) {
1423 		TCHAR buf[MAX_DPATH], *p;
1424 		if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue))
1425 			break;
1426 		p = buf;
1427 		skipspace (&p);
1428 		if (!_tcsnicmp (p, _T("[DISC]"), 6)) {
1429 			mode = 1;
1430 		} else if (!_tcsnicmp (p, _T("[ENTRY "), 7)) {
1431 			t = NULL;
1432 			mode = 2;
1433 			num = readval (p + 7);
1434 			if (num < 0)
1435 				break;
1436 			adr = control = -1;
1437 			gotlba = false;
1438 		} else if (!_tcsnicmp (p, _T("[TRACK "), 7)) {
1439 			mode = 3;
1440 			tracknum = readval (p + 7);
1441 			trackmode = -1;
1442 			if (tracknum <= 0 || tracknum > 99)
1443 				break;
1444 			t = &cdu->toc[tracknum - 1];
1445 		}
1446 		if (mode < 0)
1447 			continue;
1448 		if (mode == 1) {
1449 			if (!_tcsnicmp (p, _T("TocEntries="), 11)) {
1450 				cdu->tracks = readval (p + 11) - 3;
1451 				if (cdu->tracks <= 0 || cdu->tracks > 99)
1452 					break;
1453 			}
1454 			continue;
1455 		}
1456 		if (cdu->tracks <= 0)
1457 			break;
1458 
1459 		if (mode == 2) {
1460 
1461 			if (!_tcsnicmp (p, _T("SESSION="), 8)) {
1462 				if (readval (p + 8) != 1)
1463 					mode = -1;
1464 				continue;
1465 			} else if (!_tcsnicmp (p, _T("POINT="), 6)) {
1466 				tracknum = readval (p + 6);
1467 				if (tracknum <= 0)
1468 					break;
1469 				if (tracknum >= 0xa0 && tracknum != 0xa2) {
1470 					mode = -1;
1471 					continue;
1472 				}
1473 				if (tracknum == 0xa2)
1474 					tracknum = cdu->tracks + 1;
1475 				t = &cdu->toc[tracknum - 1];
1476 				continue;
1477 			}
1478 			if (!_tcsnicmp (p, _T("ADR="), 4))
1479 				adr = readval (p + 4);
1480 			if (!_tcsnicmp (p, _T("CONTROL="), 8))
1481 				control = readval (p + 8);
1482 			if (!_tcsnicmp (p, _T("PLBA="), 5)) {
1483 				lba = readval (p + 5);
1484 				gotlba = true;
1485 			}
1486 			if (gotlba && adr >= 0 && control >= 0) {
1487 				t->adr = adr;
1488 				t->ctrl = control;
1489 				t->address = lba;
1490 				t->offset = 0;
1491 				t->size = 2352;
1492 				t->offset = lba * t->size;
1493 				t->track = tracknum;
1494 				if ((control & 0x0c) != 4)
1495 					t->enctype = AUDENC_PCM;
1496 				if (zsub) {
1497 					t->subcode = 2;
1498 					t->subhandle = zfile_dup (zsub);
1499 					t->suboffset = 0;
1500 				}
1501 				if (zimg) {
1502 					t->handle = zfile_dup (zimg);
1503 					t->fname = my_strdup (zfile_getname (zimg));
1504 				}
1505 				mode = -1;
1506 			}
1507 
1508 		} else if (mode == 3) {
1509 
1510 			if (!_tcsnicmp (p, _T("MODE="), 5))
1511 				trackmode = _tstol (p + 5);
1512 			if (trackmode < 0 || trackmode > 2)
1513 				continue;
1514 
1515 		}
1516 
1517 	}
1518 	zfile_fclose (zimg);
1519 	zfile_fclose (zsub);
1520 	return cdu->tracks;
1521 }
1522 
parsecue(struct cdunit * cdu,struct zfile * zcue,const TCHAR * img)1523 static int parsecue (struct cdunit *cdu, struct zfile *zcue, const TCHAR *img)
1524 {
1525 	int tracknum, pregap, postgap, lastpregap, lastpostgap;
1526 	int newfile, secoffset;
1527 	uae_s64 fileoffset;
1528 	int index0;
1529 	TCHAR *fname, *fnametype;
1530 	audenc fnametypeid;
1531 	int ctrl;
1532 	mp3decoder *mp3dec = NULL;
1533 
1534 	fname = NULL;
1535 	fnametype = NULL;
1536 	tracknum = 0;
1537 	fileoffset = 0;
1538 	secoffset = 0;
1539 	newfile = 0;
1540 	ctrl = 0;
1541 	index0 = -1;
1542 	pregap = 0;
1543 	postgap = 0;
1544 	lastpregap = 0;
1545 	lastpostgap = 0;
1546 	fnametypeid = AUDENC_NONE;
1547 
1548 	write_log (_T("CUE TOC: '%s'\n"), img);
1549 	for (;;) {
1550 		TCHAR buf[MAX_DPATH], *p;
1551 		if (!zfile_fgets (buf, sizeof buf / sizeof (TCHAR), zcue))
1552 			break;
1553 
1554 		p = buf;
1555 		skipspace (&p);
1556 
1557 		if (!_tcsnicmp (p, _T("FILE"), 4)) {
1558 			p += 4;
1559 			xfree (fname);
1560 			fname = my_strdup (nextstring (&p));
1561 			fnametype = nextstring (&p);
1562 			fnametypeid = AUDENC_NONE;
1563 			if (!fnametype)
1564 				break;
1565 			if (_tcsicmp (fnametype, _T("BINARY")) && _tcsicmp (fnametype, _T("WAVE")) && _tcsicmp (fnametype, _T("MP3")) && _tcsicmp (fnametype, _T("FLAC"))) {
1566 				write_log (_T("CUE: unknown file type '%s' ('%s')\n"), fnametype, fname);
1567 			}
1568 			fnametypeid = AUDENC_PCM;
1569 			if (!_tcsicmp (fnametype, _T("MP3")))
1570 				fnametypeid = AUDENC_MP3;
1571 			else if (!_tcsicmp (fnametype, _T("FLAC")))
1572 				fnametypeid = AUDENC_FLAC;
1573 			fileoffset = 0;
1574 			newfile = 1;
1575 			ctrl = 0;
1576 		} else if (!_tcsnicmp (p, _T("FLAGS"), 5)) {
1577 			ctrl &= ~(1 | 2 | 8);
1578 			for (;;) {
1579 				TCHAR *f = nextstring (&p);
1580 				if (!f)
1581 					break;
1582 				if (!_tcsicmp (f, _T("PRE")))
1583 					ctrl |= 1;
1584 				if (!_tcsicmp (f, _T("DCP")))
1585 					ctrl |= 2;
1586 				if (!_tcsicmp (f, _T("4CH")))
1587 					ctrl |= 8;
1588 			}
1589 		} else if (!_tcsnicmp (p, _T("TRACK"), 5)) {
1590 			int size;
1591 			TCHAR *tracktype;
1592 
1593 			p += 5;
1594 			index0 = -1;
1595 			lastpregap = 0;
1596 			lastpostgap = 0;
1597 			tracknum = _tstoi (nextstring (&p));
1598 			tracktype = nextstring (&p);
1599 			if (!tracktype)
1600 				break;
1601 			size = 2352;
1602 			if (!_tcsicmp (tracktype, _T("AUDIO"))) {
1603 				ctrl &= ~4;
1604 			} else {
1605 				ctrl |= 4;
1606 				if (!_tcsicmp (tracktype, _T("MODE1/2048")))
1607 					size = 2048;
1608 				else if (!_tcsicmp (tracktype, _T("MODE1/2352")))
1609 					size = 2352;
1610 				else if (!_tcsicmp (tracktype, _T("MODE2/2336")) || !_tcsicmp (tracktype, _T("CDI/2336")))
1611 					size = 2336;
1612 				else if (!_tcsicmp (tracktype, _T("MODE2/2352")) || !_tcsicmp (tracktype, _T("CDI/2352")))
1613 					size = 2352;
1614 				else {
1615 					write_log (_T("CUE: unknown tracktype '%s' ('%s')\n"), tracktype, fname);
1616 				}
1617 			}
1618 			if (tracknum >= 1 && tracknum <= 99) {
1619 				struct cdtoc *t = &cdu->toc[tracknum - 1];
1620 				struct zfile *ztrack;
1621 
1622 				if (tracknum > 1 && newfile) {
1623 					t--;
1624 					secoffset += (int)(t->filesize / t->size);
1625 					t++;
1626 				}
1627 
1628 				newfile = 0;
1629 				ztrack = zfile_fopen (fname, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
1630 				if (!ztrack) {
1631 					TCHAR tmp[MAX_DPATH];
1632 					_tcscpy (tmp, fname);
1633 					p = tmp + _tcslen (tmp);
1634 					while (p > tmp) {
1635 						if (*p == '/' || *p == '\\') {
1636 							ztrack = zfile_fopen (p + 1, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
1637 							if (ztrack) {
1638 								xfree (fname);
1639 								fname = my_strdup (p + 1);
1640 							}
1641 							break;
1642 						}
1643 						p--;
1644 					}
1645 				}
1646 				if (!ztrack) {
1647 					TCHAR tmp[MAX_DPATH];
1648 					TCHAR *s2;
1649 					_tcscpy (tmp, zfile_getname (zcue));
1650 					s2 = _tcsrchr (tmp, '\\');
1651 					if (!s2)
1652 						s2 = _tcsrchr (tmp, '/');
1653 					if (s2) {
1654 						s2[0] = 0;
1655 						_tcscat (tmp, FSDB_DIR_SEPARATOR_S);
1656 						_tcscat (tmp, fname);
1657 						ztrack = zfile_fopen (tmp, _T("rb"), ZFD_ARCHIVE | ZFD_DELAYEDOPEN);
1658 					}
1659 				}
1660 				t->track = tracknum;
1661 				t->ctrl = ctrl;
1662 				t->adr = 1;
1663 				t->handle = ztrack;
1664 				t->size = size;
1665 				t->fname = my_strdup (fname);
1666 				if (tracknum > cdu->tracks)
1667 					cdu->tracks = tracknum;
1668 				if (t->handle)
1669 					t->filesize = zfile_size (t->handle);
1670 			}
1671 		} else if (!_tcsnicmp (p, _T("PREGAP"), 6)) {
1672 			TCHAR *tt;
1673 			int tn;
1674 			p += 6;
1675 			tt = nextstring (&p);
1676 			tn = _tstoi (tt) * 60 * 75;
1677 			tn += _tstoi (tt + 3) * 75;
1678 			tn += _tstoi (tt + 6);
1679 			pregap += tn;
1680 			lastpregap = tn;
1681 		} else if (!_tcsnicmp (p, _T("POSTGAP"), 7)) {
1682 			struct cdtoc *t = &cdu->toc[tracknum - 1];
1683 			TCHAR *tt;
1684 			int tn;
1685 			p += 7;
1686 			tt = nextstring (&p);
1687 			tn = _tstoi (tt) * 60 * 75;
1688 			tn += _tstoi (tt + 3) * 75;
1689 			tn += _tstoi (tt + 6);
1690 			postgap += tn;
1691 			lastpostgap = tn;
1692 		} else if (!_tcsnicmp (p, _T("INDEX"), 5)) {
1693 			int idxnum;
1694 			int tn = 0;
1695 			TCHAR *tt;
1696 			p += 5;
1697 			idxnum = _tstoi (nextstring (&p));
1698 			tt = nextstring (&p);
1699 			tn = _tstoi (tt) * 60 * 75;
1700 			tn += _tstoi (tt + 3) * 75;
1701 			tn += _tstoi (tt + 6);
1702 			if (idxnum == 0) {
1703 				index0 = tn;
1704 			} else if (idxnum == 1 && tracknum >= 1 && tracknum <= 99) {
1705 				struct cdtoc *t = &cdu->toc[tracknum - 1];
1706 				if (!t->address) {
1707 					t->address = tn + secoffset;
1708 					t->address += pregap;
1709 					t->pregap = lastpregap;
1710 					t->postgap = lastpostgap;
1711 					if (index0 >= 0) {
1712 						t->index1 = tn - index0;
1713 					}
1714 					if (lastpregap && !secoffset) {
1715 						t->index1 = lastpregap;
1716 					}
1717 					int blockoffset = t->address - t->index1;
1718 					if (tracknum > 1)
1719 						blockoffset -= t[-1].address - t[-1].index1;
1720 					fileoffset += blockoffset * t[-1].size;
1721 					if (!secoffset) {
1722 						// secoffset == 0: same file contained also previous track
1723 						t->offset = fileoffset - pregap * t->size;
1724 					}
1725 					t->address += postgap;
1726 					if (fnametypeid == AUDENC_PCM && t->handle) {
1727 						struct zfile *zf = t->handle;
1728 						uae_u8 buf[16] = { 0 };
1729 						zfile_fread (buf, 12, 1, zf);
1730 						if (!memcmp (buf, "RIFF", 4) && !memcmp (buf + 8, "WAVE", 4)) {
1731 							int size;
1732 							for (;;) {
1733 								memset (buf, 0, sizeof buf);
1734 								if (zfile_fread (buf, 8, 1, zf) != 1)
1735 									break;
1736 								size = (buf[4] << 0) | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
1737 								if (!memcmp (buf, "data", 4))
1738 									break;
1739 								if (size <= 0)
1740 									break;
1741 								zfile_fseek (zf, size, SEEK_CUR);
1742 							}
1743 							t->offset += zfile_ftell (zf);
1744 							t->filesize = size;
1745 						}
1746 						t->enctype = fnametypeid;
1747 					} else if (fnametypeid == AUDENC_MP3 && t->handle) {
1748 						if (!mp3dec) {
1749 							try {
1750 								mp3dec = new mp3decoder();
1751 							} catch (exception) { }
1752 						}
1753 						if (mp3dec) {
1754 							t->offset = 0;
1755 							t->filesize = mp3dec->getsize (t->handle);
1756 							if (t->filesize)
1757 								t->enctype = fnametypeid;
1758 						}
1759 					} else if (fnametypeid == AUDENC_FLAC && t->handle) {
1760 						flac_get_size (t);
1761 						if (t->filesize)
1762 							t->enctype = fnametypeid;
1763 					}
1764 				}
1765 			}
1766 		}
1767 	}
1768 
1769 	struct cdtoc *t = &cdu->toc[cdu->tracks - 1];
1770 	uae_s64 size = t->filesize;
1771 	if (!secoffset)
1772 		size -= fileoffset;
1773 	if (size < 0)
1774 		size = 0;
1775 	size /= t->size;
1776 	cdu->toc[cdu->tracks].address = t->address + (int)size;
1777 
1778 	xfree (fname);
1779 
1780 	delete mp3dec;
1781 
1782 	return cdu->tracks;
1783 }
1784 
parse_image(struct cdunit * cdu,const TCHAR * img)1785 static int parse_image (struct cdunit *cdu, const TCHAR *img)
1786 {
1787 	struct zfile *zcue;
1788 	int i;
1789 	const TCHAR *ext;
1790 	int secoffset;
1791 
1792 	secoffset = 0;
1793 	cdu->tracks = 0;
1794 	if (!img)
1795 		return 0;
1796 	zcue = zfile_fopen (img, _T("rb"), ZFD_ARCHIVE | ZFD_CD | ZFD_DELAYEDOPEN);
1797 	if (!zcue)
1798 		return 0;
1799 
1800 	ext = _tcsrchr (zfile_getname (zcue), '.');
1801 	if (ext) {
1802 		TCHAR curdir[MAX_DPATH];
1803 		TCHAR oldcurdir[MAX_DPATH], *p;
1804 
1805 		ext++;
1806 		oldcurdir[0] = 0;
1807 		_tcscpy (curdir, img);
1808 		p = curdir + _tcslen (curdir);
1809 		while (p > curdir) {
1810 			if (*p == '/' || *p == '\\')
1811 				break;
1812 			p--;
1813 		}
1814 		*p = 0;
1815 		if (p > curdir)
1816 			my_setcurrentdir (curdir, oldcurdir);
1817 
1818 		if (!_tcsicmp (ext, _T("cue"))) {
1819 			parsecue (cdu, zcue, img);
1820 		} else if (!_tcsicmp (ext, _T("ccd"))) {
1821 			parseccd (cdu, zcue, img);
1822 		} else if (!_tcsicmp (ext, _T("mds"))) {
1823 			parsemds (cdu, zcue, img);
1824 #ifdef WITH_CHD
1825 		} else if (!_tcsicmp (ext, _T("chd"))) {
1826 			if (oldcurdir[0])
1827 				my_setcurrentdir (oldcurdir, NULL);
1828 			parsechd (cdu, zcue, img);
1829 #endif
1830 		}
1831 
1832 		if (oldcurdir[0])
1833 			my_setcurrentdir (oldcurdir, NULL);
1834 	}
1835 	if (!cdu->tracks) {
1836 		uae_u64 siz = zfile_size (zcue);
1837 		if (siz >= 16384 && ((siz % 2048) == 0 || (siz % 2352) == 0)) {
1838 			struct cdtoc *t = &cdu->toc[0];
1839 			cdu->tracks = 1;
1840 			t->ctrl = 4;
1841 			t->adr = 1;
1842 			t->fname = my_strdup (img);
1843 			t->handle = zcue;
1844 			t->size = (siz % 2048) == 0 ? 2048 : 2352;
1845 			t->filesize = siz;
1846 			t->track = 1;
1847 			write_log (_T("CD: plain CD image mounted!\n"));
1848 			cdu->toc[1].address = t->address + (int)(t->filesize / t->size);
1849 			zcue = NULL;
1850 		}
1851 	}
1852 
1853 	if (!cdu->tracks)
1854 		write_log (_T("CD: couldn't mount '%s'!\n"), img);
1855 
1856 	for (i = 0; i <= cdu->tracks; i++) {
1857 		struct cdtoc *t = &cdu->toc[i];
1858 		uae_u32 msf;
1859 		if (t->pregap) {
1860 			msf = lsn2msf (t->pregap - 150);
1861 			write_log (_T("   PREGAP : %02d:%02d:%02d\n"), (msf >> 16) & 0x7fff, (msf >> 8) & 0xff, (msf >> 0) & 0xff);
1862 		}
1863 		if (t->index1) {
1864 			msf = lsn2msf (t->index1 - 150);
1865 			write_log (_T("   INDEX1 : %02d:%02d:%02d\n"), (msf >> 16) & 0x7fff, (msf >> 8) & 0xff, (msf >> 0) & 0xff);
1866 		}
1867 		if (i < cdu->tracks)
1868 			write_log (_T("%2d: "), i + 1);
1869 		else
1870 			write_log (_T("    "));
1871 		msf = lsn2msf (t->address);
1872 		write_log (_T("%7d %02d:%02d:%02d"),
1873 			t->address, (msf >> 16) & 0x7fff, (msf >> 8) & 0xff, (msf >> 0) & 0xff);
1874 		if (i < cdu->tracks) {
1875 			write_log (_T(" %s %x %10lld %10lld %s%s"),
1876 				(t->ctrl & 4) ? _T("DATA    ") : (t->subcode ? _T("CDA+SUB") : _T("CDA     ")),
1877 				t->ctrl, t->offset, t->filesize,
1878 				t->extrainfo ? t->extrainfo : _T(""),
1879 				t->handle == NULL && t->enctype != ENC_CHD ? _T("[FILE ERROR]") : _T(""));
1880 		}
1881 		write_log (_T("\n"));
1882 		if (i < cdu->tracks)
1883 			write_log (_T(" - %s\n"), t->fname);
1884 		if (t->handle && !t->filesize)
1885 			t->filesize = zfile_size (t->handle);
1886 		if (t->postgap) {
1887 			msf = lsn2msf (t->postgap - 150);
1888 			write_log (_T("   POSTGAP: %02d:%02d:%02d\n"), (msf >> 16) & 0x7fff, (msf >> 8) & 0xff, (msf >> 0) & 0xff);
1889 		}
1890 	}
1891 
1892 	cdu->blocksize = 2048;
1893 	cdu->cdsize = (uae_u64)cdu->toc[cdu->tracks].address * cdu->blocksize;
1894 
1895 
1896 	zfile_fclose (zcue);
1897 	return 1;
1898 }
1899 
ismedia(int unitnum,int quick)1900 static int ismedia (int unitnum, int quick)
1901 {
1902 	struct cdunit *cdu = &cdunits[unitnum];
1903 	if (!cdu->enabled)
1904 		return -1;
1905 	return cdu->tracks > 0 ? 1 : 0;
1906 }
1907 
info_device(int unitnum,struct device_info * di,int quick,int session)1908 static struct device_info *info_device (int unitnum, struct device_info *di, int quick, int session)
1909 {
1910 	struct cdunit *cdu = &cdunits[unitnum];
1911 	memset (di, 0, sizeof (struct device_info));
1912 	if (!cdu->enabled)
1913 		return NULL;
1914 	di->open = cdu->open;
1915 	di->removable = 1;
1916 	di->bus = unitnum;
1917 	di->target = 0;
1918 	di->lun = 0;
1919 	di->media_inserted = 0;
1920 	di->bytespersector = 2048;
1921 	di->mediapath[0] = 0;
1922 	di->cylinders = 1;
1923 	di->trackspercylinder = 1;
1924 	di->sectorspertrack = (int)(cdu->cdsize / di->bytespersector);
1925 	if (ismedia (unitnum, 1)) {
1926 		di->media_inserted = 1;
1927 		_tcscpy (di->mediapath, cdu->imgname);
1928 	}
1929 	memset (&di->toc, 0, sizeof (struct cd_toc_head));
1930 	command_toc (unitnum, &di->toc);
1931 	di->write_protected = 1;
1932 	di->type = INQ_ROMD;
1933 	di->unitnum = unitnum + 1;
1934 	if (di->mediapath[0]) {
1935 		_tcscpy (di->label, _T("IMG:"));
1936 		_tcscat (di->label, di->mediapath);
1937 	} else {
1938 		_tcscpy (di->label, _T("IMG:<EMPTY>"));
1939 	}
1940 	_tcscpy (di->vendorid, _T("UAE"));
1941 	_stprintf (di->productid, _T("SCSICD%d"), unitnum);
1942 	_tcscpy (di->revision, _T("1.0"));
1943 	di->backend = _T("IMAGE");
1944 	return di;
1945 }
1946 
unload_image(struct cdunit * cdu)1947 static void unload_image (struct cdunit *cdu)
1948 {
1949 	int i;
1950 
1951 	for (i = 0; i < sizeof cdu->toc / sizeof (struct cdtoc); i++) {
1952 		struct cdtoc *t = &cdu->toc[i];
1953 		zfile_fclose (t->handle);
1954 		if (t->handle != t->subhandle)
1955 			zfile_fclose (t->subhandle);
1956 		xfree (t->fname);
1957 		xfree (t->data);
1958 		xfree (t->subdata);
1959 		xfree (t->extrainfo);
1960 	}
1961 #ifdef WITH_CHD
1962 	cdrom_close (cdu->chd_cdf);
1963 	cdu->chd_cdf = NULL;
1964 	if (cdu->chd_f)
1965 		cdu->chd_f->close();
1966 	cdu->chd_f = NULL;
1967 #endif
1968 	memset (cdu->toc, 0, sizeof cdu->toc);
1969 	cdu->tracks = 0;
1970 	cdu->cdsize = 0;
1971 }
1972 
1973 
open_device(int unitnum,const TCHAR * ident,int flags)1974 static int open_device (int unitnum, const TCHAR *ident, int flags)
1975 {
1976 	struct cdunit *cdu = &cdunits[unitnum];
1977 	int ret = 0;
1978 
1979 	if (!cdu->open) {
1980 		uae_sem_init (&cdu->sub_sem, 0, 1);
1981 		cdu->imgname[0] = 0;
1982 		if (ident)
1983 			_tcscpy (cdu->imgname, ident);
1984 		parse_image (cdu, ident);
1985 		cdu->open = true;
1986 		cdu->enabled = true;
1987 		cdu->cdda_volume[0] = 0x7fff;
1988 		cdu->cdda_volume[1] = 0x7fff;
1989 		if (cdimage_unpack_thread == 0) {
1990 			init_comm_pipe (&unpack_pipe, 10, 1);
1991 			uae_start_thread (_T("cdimage_unpack"), cdda_unpack_func, NULL, NULL);
1992 			while (cdimage_unpack_thread == 0)
1993 				Sleep (10);
1994 		}
1995 		ret = 1;
1996 	}
1997 	blkdev_cd_change (unitnum, cdu->imgname);
1998 	return ret;
1999 }
2000 
close_device(int unitnum)2001 static void close_device (int unitnum)
2002 {
2003 	struct cdunit *cdu = &cdunits[unitnum];
2004 	if (cdu->open) {
2005 		cdda_stop (cdu);
2006 		cdu->open = false;
2007 		if (cdimage_unpack_thread) {
2008 			cdimage_unpack_thread = 0;
2009 			write_comm_pipe_u32 (&unpack_pipe, -1, 0);
2010 			write_comm_pipe_u32 (&unpack_pipe, -1, 1);
2011 			while (cdimage_unpack_thread == 0)
2012 				Sleep (10);
2013 			cdimage_unpack_thread = 0;
2014 			destroy_comm_pipe (&unpack_pipe);
2015 		}
2016 		unload_image (cdu);
2017 		uae_sem_destroy (&cdu->sub_sem);
2018 	}
2019 	blkdev_cd_change (unitnum, cdu->imgname);
2020 }
2021 
close_bus(void)2022 static void close_bus (void)
2023 {
2024 	if (!bus_open) {
2025 		write_log (_T("IMAGE close_bus() when already closed!\n"));
2026 		return;
2027 	}
2028 	for (int i = 0; i < MAX_TOTAL_SCSI_DEVICES; i++) {
2029 		struct cdunit *cdu = &cdunits[i];
2030 		if (cdu->open)
2031 			close_device (i);
2032 		cdu->enabled = false;
2033 	}
2034 	bus_open = 0;
2035 	uae_sem_destroy(&play_sem);
2036 	write_log (_T("IMAGE driver closed.\n"));
2037 }
2038 
open_bus(int flags)2039 static int open_bus (int flags)
2040 {
2041 	if (bus_open) {
2042 		write_log (_T("IOCTL open_bus() more than once!\n"));
2043 		return 1;
2044 	}
2045 	bus_open = 1;
2046 	uae_sem_init(&play_sem, 0, 1);
2047 	write_log (_T("Image driver open.\n"));
2048 	return 1;
2049 }
2050 
2051 struct device_functions devicefunc_cdimage = {
2052 	_T("IMAGE"),
2053 	open_bus, close_bus, open_device, close_device, info_device,
2054 	0, 0, 0,
2055 	command_pause, command_stop, command_play, command_volume, command_qcode,
2056 	command_toc, command_read, command_rawread, 0,
2057 	0, ismedia
2058 };
2059