1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4 
5 
6     CD-i Mono-I CDIC MCU simulation
7     -------------------
8 
9     written by Ryan Holtz
10 
11 
12 *******************************************************************************
13 
14 STATUS:
15 
16 - Just enough for the Mono-I CD-i board to work somewhat properly.
17 
18 TODO:
19 
20 - Decapping and proper emulation.
21 
22 *******************************************************************************/
23 
24 #include "emu.h"
25 #include "machine/cdicdic.h"
26 
27 #include "cdrom.h"
28 #include "romload.h"
29 #include "sound/cdda.h"
30 
31 #define LOG_DECODES     (1 << 1)
32 #define LOG_SAMPLES     (1 << 2)
33 #define LOG_COMMANDS    (1 << 3)
34 #define LOG_SECTORS     (1 << 4)
35 #define LOG_IRQS        (1 << 5)
36 #define LOG_READS       (1 << 6)
37 #define LOG_WRITES      (1 << 7)
38 #define LOG_UNKNOWNS    (1 << 8)
39 #define LOG_RAM         (1 << 9)
40 #define LOG_ALL         (LOG_DECODES | LOG_SAMPLES | LOG_COMMANDS | LOG_SECTORS | LOG_IRQS | LOG_READS | LOG_WRITES | LOG_UNKNOWNS | LOG_RAM)
41 
42 #define VERBOSE         (LOG_ALL)
43 #include "logmacro.h"
44 
45 // device type definition
46 DEFINE_DEVICE_TYPE(CDI_CDIC, cdicdic_device, "cdicdic", "CD-i CDIC")
47 
48 
49 //**************************************************************************
50 //  GLOBAL VARIABLES
51 //**************************************************************************
52 
53 const int32_t cdicdic_device::s_cdic_adpcm_filter_coef[5][2] =
54 {
55 	{ 0,0 },
56 	{ 60,0 },
57 	{ 115,-52 },
58 	{ 98,-55 },
59 	{ 122,-60 },
60 };
61 
62 //**************************************************************************
63 //  INLINES
64 //**************************************************************************
65 
is_valid_sample_buf(uint16_t addr) const66 int cdicdic_device::is_valid_sample_buf(uint16_t addr) const
67 {
68 	const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr;
69 	if (cdram8[10] != 0xff)
70 	{
71 		return 1;
72 	}
73 	return 0;
74 }
75 
sample_buf_freq(uint16_t addr) const76 double cdicdic_device::sample_buf_freq(uint16_t addr) const
77 {
78 	const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr + 8;
79 	switch (cdram8[2] & 0x3f)
80 	{
81 		case 0:
82 		case 1:
83 		case 16:
84 		case 17:
85 			return clock2() / 512.0f;
86 
87 		case 4:
88 		case 5:
89 			return clock2() / 1024.0f;
90 
91 		default:
92 			return clock2() / 1024.0f;
93 	}
94 }
95 
sample_buf_size(uint16_t addr) const96 int cdicdic_device::sample_buf_size(uint16_t addr) const
97 {
98 	const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr + 8;
99 	switch (cdram8[2] & 0x3f)
100 	{
101 		case 0:
102 		case 4:
103 			return 4;
104 
105 		case 1:
106 		case 5:
107 		case 16:
108 			return 2;
109 
110 		case 17:
111 			return 1;
112 
113 		default:
114 			return 2;
115 	}
116 }
117 
clamp(int16_t in)118 static inline int16_t clamp(int16_t in)
119 {
120 	return in;
121 }
122 
123 //**************************************************************************
124 //  MEMBER FUNCTIONS
125 //**************************************************************************
126 
increment_cdda_frame_bcd(uint32_t bcd)127 uint32_t cdicdic_device::increment_cdda_frame_bcd(uint32_t bcd)
128 {
129 	uint8_t nybbles[6] =
130 	{
131 		static_cast<uint8_t>(bcd & 0x0000000f),
132 		static_cast<uint8_t>((bcd & 0x000000f0) >> 4),
133 		static_cast<uint8_t>((bcd & 0x00000f00) >> 8),
134 		static_cast<uint8_t>((bcd & 0x0000f000) >> 12),
135 		static_cast<uint8_t>((bcd & 0x000f0000) >> 16),
136 		static_cast<uint8_t>((bcd & 0x00f00000) >> 20)
137 	};
138 	nybbles[0]++;
139 	if (nybbles[0] == 5 && nybbles[1] == 7)
140 	{
141 		nybbles[0] = 0;
142 		nybbles[1] = 0;
143 		nybbles[2]++;
144 	}
145 	else if (nybbles[0] == 10)
146 	{
147 		nybbles[1]++;
148 	}
149 	if (nybbles[2] == 10)
150 	{
151 		nybbles[3]++;
152 		nybbles[2] = 0;
153 	}
154 	if (nybbles[3] == 6)
155 	{
156 		nybbles[4]++;
157 		nybbles[3] = 0;
158 	}
159 	if (nybbles[4] == 10)
160 	{
161 		nybbles[5]++;
162 		nybbles[4] = 0;
163 	}
164 	return (nybbles[5] << 20) | (nybbles[4] << 16) | (nybbles[3] << 12) | (nybbles[2] << 8) | (nybbles[1] << 4) | nybbles[0];
165 }
166 
increment_cdda_sector_bcd(uint32_t bcd)167 uint32_t cdicdic_device::increment_cdda_sector_bcd(uint32_t bcd)
168 {
169 	uint8_t nybbles[6] =
170 	{
171 		static_cast<uint8_t>(bcd & 0x0000000f),
172 		static_cast<uint8_t>((bcd & 0x000000f0) >> 4),
173 		static_cast<uint8_t>((bcd & 0x00000f00) >> 8),
174 		static_cast<uint8_t>((bcd & 0x0000f000) >> 12),
175 		static_cast<uint8_t>((bcd & 0x000f0000) >> 16),
176 		static_cast<uint8_t>((bcd & 0x00f00000) >> 20)
177 	};
178 	nybbles[2]++;
179 	if (nybbles[2] == 10)
180 	{
181 		nybbles[3]++;
182 		nybbles[2] = 0;
183 	}
184 	if (nybbles[3] == 6)
185 	{
186 		nybbles[4]++;
187 		nybbles[3] = 0;
188 	}
189 	if (nybbles[4] == 10)
190 	{
191 		nybbles[5]++;
192 		nybbles[4] = 0;
193 	}
194 	return (nybbles[5] << 20) | (nybbles[4] << 16) | (nybbles[3] << 12) | (nybbles[2] << 8) | (nybbles[1] << 4) | nybbles[0];
195 }
196 
decode_xa_mono(int32_t * cdic_xa_last,const uint8_t * xa,int16_t * dp)197 void cdicdic_device::decode_xa_mono(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
198 {
199 	int32_t l0 = cdic_xa_last[0];
200 	int32_t l1 = cdic_xa_last[1];
201 
202 	for (int32_t b = 0; b < 18; b++)
203 	{
204 		for (int32_t s = 0; s < 4; s++)
205 		{
206 			uint8_t flags = xa[(4 + (s << 1)) ^ 1];
207 			uint8_t shift = flags & 0xf;
208 			uint8_t filter = flags >> 4;
209 			int32_t f0 = s_cdic_adpcm_filter_coef[filter][0];
210 			int32_t f1 = s_cdic_adpcm_filter_coef[filter][1];
211 
212 			for (int32_t i = 0; i < 28; i++)
213 			{
214 				int16_t d = (xa[(16 + (i << 2) + s) ^ 1] & 0xf) << 12;
215 				d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
216 				*dp = d;
217 				dp++;
218 				l1 = l0;
219 				l0 = d;
220 			}
221 
222 			flags = xa[(5 + (s << 1)) ^ 1];
223 			shift = flags & 0xf;
224 			filter = flags >> 4;
225 			f0 = s_cdic_adpcm_filter_coef[filter][0];
226 			f1 = s_cdic_adpcm_filter_coef[filter][1];
227 
228 			for (int32_t i = 0; i < 28; i++)
229 			{
230 				int16_t d = (xa[(16 + (i << 2) + s) ^ 1] >> 4) << 12;
231 				d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
232 				*dp = d;
233 				dp++;
234 				l1 = l0;
235 				l0 = d;
236 			}
237 		}
238 
239 		xa += 128;
240 	}
241 
242 	cdic_xa_last[0] = l0;
243 	cdic_xa_last[1] = l1;
244 }
245 
decode_xa_mono8(int * cdic_xa_last,const unsigned char * xa,signed short * dp)246 void cdicdic_device::decode_xa_mono8(int *cdic_xa_last, const unsigned char *xa, signed short *dp)
247 {
248 	int32_t l0 = cdic_xa_last[0];
249 	int32_t l1 = cdic_xa_last[1];
250 
251 	for (int32_t b = 0; b < 18; b++)
252 	{
253 		for (int32_t s = 0; s < 4; s++)
254 		{
255 			uint8_t flags = xa[(4 + s) ^ 1];
256 			uint8_t shift = flags & 0xf;
257 			uint8_t filter = flags >> 4;
258 			int32_t f0 = s_cdic_adpcm_filter_coef[filter][0];
259 			int32_t f1 = s_cdic_adpcm_filter_coef[filter][1];
260 
261 			for (int32_t i = 0; i < 28; i++)
262 			{
263 				int16_t d = (xa[(16 + (i << 2) + s) ^ 1] << 8);
264 				d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
265 				*dp = d;
266 				dp++;
267 				l1 = l0;
268 				l0 = d;
269 			}
270 		}
271 
272 		xa += 128;
273 	}
274 
275 	cdic_xa_last[0] = l0;
276 	cdic_xa_last[1] = l1;
277 }
278 
decode_xa_stereo(int32_t * cdic_xa_last,const uint8_t * xa,int16_t * dp)279 void cdicdic_device::decode_xa_stereo(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
280 {
281 	int32_t l0 = cdic_xa_last[0];
282 	int32_t l1 = cdic_xa_last[1];
283 	int32_t l2 = cdic_xa_last[2];
284 	int32_t l3 = cdic_xa_last[3];
285 
286 	for (int32_t b = 0; b < 18; b++)
287 	{
288 		for (int32_t s = 0; s < 4; s++)
289 		{
290 			uint8_t flags0 = xa[(4 + (s << 1)) ^ 1];
291 			uint8_t shift0 = flags0 & 0xf;
292 			uint8_t filter0 = flags0 >> 4;
293 			uint8_t flags1 = xa[(5 + (s << 1)) ^ 1];
294 			uint8_t shift1 = flags1 & 0xf;
295 			uint8_t filter1 = flags1 >> 4;
296 
297 			int32_t f0 = s_cdic_adpcm_filter_coef[filter0][0];
298 			int32_t f1 = s_cdic_adpcm_filter_coef[filter0][1];
299 			int32_t f2 = s_cdic_adpcm_filter_coef[filter1][0];
300 			int32_t f3 = s_cdic_adpcm_filter_coef[filter1][1];
301 
302 			for (int32_t i = 0; i < 28; i++)
303 			{
304 				int16_t d = xa[(16 + (i << 2) + s) ^ 1];
305 				int16_t d0 = (d & 0xf) << 12;
306 				int16_t d1 = (d >> 4) << 12;
307 				d0 = clamp((d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
308 				*dp = d0;
309 				dp++;
310 				l1 = l0;
311 				l0 = d0;
312 
313 				d1 = clamp((d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 32) >> 6));
314 				*dp = d1;
315 				dp++;
316 				l3 = l2;
317 				l2 = d1;
318 			}
319 		}
320 
321 		xa += 128;
322 	}
323 
324 	cdic_xa_last[0] = l0;
325 	cdic_xa_last[1] = l1;
326 	cdic_xa_last[2] = l2;
327 	cdic_xa_last[3] = l3;
328 }
329 
decode_xa_stereo8(int32_t * cdic_xa_last,const uint8_t * xa,int16_t * dp)330 void cdicdic_device::decode_xa_stereo8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
331 {
332 	int32_t l0 = cdic_xa_last[0];
333 	int32_t l1 = cdic_xa_last[1];
334 	int32_t l2 = cdic_xa_last[2];
335 	int32_t l3 = cdic_xa_last[3];
336 
337 	for (int32_t b = 0; b < 18; b++)
338 	{
339 		for (int32_t s = 0; s < 4; s += 2)
340 		{
341 			uint8_t flags0 = xa[(4 + s) ^ 1];
342 			uint8_t shift0 = flags0 & 0xf;
343 			uint8_t filter0 = flags0 >> 4;
344 			uint8_t flags1 = xa[(5 + s) ^ 1];
345 			uint8_t shift1 = flags1 & 0xf;
346 			uint8_t filter1 = flags1 >> 4;
347 			int32_t f0 = s_cdic_adpcm_filter_coef[filter0][0];
348 			int32_t f1 = s_cdic_adpcm_filter_coef[filter0][1];
349 			int32_t f2 = s_cdic_adpcm_filter_coef[filter1][0];
350 			int32_t f3 = s_cdic_adpcm_filter_coef[filter1][1];
351 
352 			for (int32_t i = 0; i < 28; i++)
353 			{
354 				int16_t d0 = (xa[(16 + (i << 2) + s + 0) ^ 1] << 8);
355 				int16_t d1 = (xa[(16 + (i << 2) + s + 1) ^ 1] << 8);
356 
357 				d0 = clamp((d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
358 				*dp = d0;
359 				dp++;
360 				l1 = l0;
361 				l0 = d0;
362 
363 				d1 = clamp((d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 32) >> 6));
364 				*dp = d1;
365 				dp++;
366 				l3 = l2;
367 				l2 = d1;
368 			}
369 		}
370 
371 		xa += 128;
372 	}
373 
374 	cdic_xa_last[0] = l0;
375 	cdic_xa_last[1] = l1;
376 	cdic_xa_last[2] = l2;
377 	cdic_xa_last[3] = l3;
378 }
379 
play_audio_sector()380 void cdicdic_device::play_audio_sector()
381 {
382 }
383 
decode_audio_sector(const uint8_t * xa,int32_t triggered)384 void cdicdic_device::decode_audio_sector(const uint8_t *xa, int32_t triggered)
385 {
386 	// Get XA format from sector header
387 	const uint8_t *hdr = xa + 4;
388 	int32_t channels;
389 	int32_t bits = 4;
390 
391 	if (hdr[2] == 0xff && triggered == 1)
392 	{
393 		return;
394 	}
395 
396 	int16_t *samples = &m_samples[m_decode_addr == 0x2800 ? 0 : 1][0];
397 	LOGMASKED(LOG_DECODES, "%s: decode_audio_sector: got header type %02x\n", machine().describe_context(), hdr[2]);
398 
399 	switch (hdr[2] & 0x3f)   // ignore emphasis and reserved bits
400 	{
401 		case 0:
402 			channels = 1;
403 			m_audio_sample_freq = clock2() / 512.0f; // / 1024.0f;
404 			bits = 4;
405 			m_audio_sample_size = 4;
406 			break;
407 
408 		case 1:
409 			channels = 2;
410 			m_audio_sample_freq = clock2() / 512.0f;
411 			bits = 4;
412 			m_audio_sample_size = 2;
413 			break;
414 
415 		case 4:
416 			channels = 1;
417 			m_audio_sample_freq = clock2() / 1024.0f;   ///2.0f;
418 			bits = 4;
419 			m_audio_sample_size = 4;
420 			break;
421 
422 		case 5:
423 			channels = 2;
424 			m_audio_sample_freq = clock2() / 1024.0f;   //37800.0f/2.0f;
425 			bits = 4;
426 			m_audio_sample_size = 2;
427 			break;
428 
429 		case 16:
430 			channels = 1;
431 			m_audio_sample_freq = clock2() / 512.0f;
432 			bits = 8;
433 			m_audio_sample_size = 2;
434 			break;
435 
436 		case 17:
437 			channels = 2;
438 			m_audio_sample_freq = clock2() / 512.0f;
439 			bits = 8;
440 			m_audio_sample_size = 1;
441 			break;
442 
443 		default:
444 			fatalerror("play_xa: unhandled xa mode %08x\n", hdr[2]);
445 	}
446 
447 	m_dmadac[0]->set_frequency(m_audio_sample_freq);
448 	m_dmadac[1]->set_frequency(m_audio_sample_freq);
449 
450 	switch (channels)
451 	{
452 		case 1:
453 			switch (bits)
454 			{
455 				case 4:
456 					decode_xa_mono(m_xa_last, hdr + 4, samples);
457 					for (int32_t index = 18*28*8 - 1; index >= 0; index--)
458 					{
459 						samples[index*2 + 1] = samples[index];
460 						samples[index*2 + 0] = samples[index];
461 					}
462 					samples[18*28*16 + 0] = samples[18*28*16 + 2] = samples[18*28*16 + 4] = samples[18*28*16 + 6] = samples[18*28*16 + 8] = samples[18*28*16 + 10] = samples[18*28*16 + 12] = samples[18*28*16 + 14] = samples[18*28*16 - 2];
463 					samples[18*28*16 + 1] = samples[18*28*16 + 3] = samples[18*28*16 + 5] = samples[18*28*16 + 7] = samples[18*28*16 + 9] = samples[18*28*16 + 11] = samples[18*28*16 + 13] = samples[18*28*16 + 15] = samples[18*28*16 - 1];
464 					break;
465 				case 8:
466 					decode_xa_mono8(m_xa_last, hdr + 4, samples);
467 					for (int32_t index = 18*28*8 - 1; index >= 0; index--)
468 					{
469 						samples[index*2 + 1] = samples[index];
470 						samples[index*2 + 0] = samples[index];
471 					}
472 					samples[18*28*8 + 0] = samples[18*28*8 + 2] = samples[18*28*8 + 4] = samples[18*28*8 + 6] = samples[18*28*8 + 8] = samples[18*28*8 + 10] = samples[18*28*8 + 12] = samples[18*28*8 + 14] = samples[18*28*8 - 2];
473 					samples[18*28*8 + 1] = samples[18*28*8 + 3] = samples[18*28*8 + 5] = samples[18*28*8 + 7] = samples[18*28*8 + 9] = samples[18*28*8 + 11] = samples[18*28*8 + 13] = samples[18*28*8 + 15] = samples[18*28*8 - 1];
474 					break;
475 			}
476 			break;
477 		case 2:
478 			switch (bits)
479 			{
480 				case 4:
481 					decode_xa_stereo(m_xa_last, hdr + 4, samples);
482 					samples[18*28*8 + 0] = samples[18*28*8 + 2] = samples[18*28*8 + 4] = samples[18*28*8 + 6] = samples[18*28*8 + 8] = samples[18*28*8 + 10] = samples[18*28*8 + 12] = samples[18*28*8 + 14] = samples[18*28*8 - 2];
483 					samples[18*28*8 + 1] = samples[18*28*8 + 3] = samples[18*28*8 + 5] = samples[18*28*8 + 7] = samples[18*28*8 + 9] = samples[18*28*8 + 11] = samples[18*28*8 + 13] = samples[18*28*8 + 15] = samples[18*28*8 - 1];
484 					//fwrite(samples, 1, 18*28*4*m_audio_sample_size, temp_adpcm);
485 					break;
486 				case 8:
487 					decode_xa_stereo8(m_xa_last, hdr + 4, samples);
488 					samples[18*28*4 + 0] = samples[18*28*4 + 2] = samples[18*28*4 + 4] = samples[18*28*4 + 6] = samples[18*28*4 + 8] = samples[18*28*4 + 10] = samples[18*28*4 + 12] = samples[18*28*4 + 14] = samples[18*28*4 - 2];
489 					samples[18*28*4 + 1] = samples[18*28*4 + 3] = samples[18*28*4 + 5] = samples[18*28*4 + 7] = samples[18*28*4 + 9] = samples[18*28*4 + 11] = samples[18*28*4 + 13] = samples[18*28*4 + 15] = samples[18*28*4 - 1];
490 					break;
491 			}
492 			break;
493 	}
494 
495 	for (int i = 0; i < 2; i++)
496 	{
497 		m_dmadac[i]->enable(1);
498 		m_dmadac[i]->transfer(i, 1, 2, 18*28*2*m_audio_sample_size, &m_samples[m_decode_addr == 0x2800 ? 0 : 1][0]);
499 		m_dmadac[i]->flush();
500 	}
501 }
502 
TIMER_CALLBACK_MEMBER(cdicdic_device::periodic_sample_trigger)503 TIMER_CALLBACK_MEMBER( cdicdic_device::periodic_sample_trigger )
504 {
505 	// Indicate that data has been decoded
506 	LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
507 	m_audio_buffer |= 0x8000;
508 
509 	// Set the CDIC interrupt line
510 	//LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
511 	//m_intreq_callback(ASSERT_LINE);
512 }
513 
TIMER_CALLBACK_MEMBER(cdicdic_device::initial_sample_trigger)514 TIMER_CALLBACK_MEMBER( cdicdic_device::initial_sample_trigger )
515 {
516 	// Indicate that data has been decoded
517 	LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
518 	m_audio_buffer |= 0x8000;
519 
520 	// Set the CDIC interrupt line
521 	LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
522 	m_intreq_callback(ASSERT_LINE);
523 
524 	sample_trigger();
525 }
526 
TIMER_CALLBACK_MEMBER(cdicdic_device::audio_sample_trigger)527 TIMER_CALLBACK_MEMBER( cdicdic_device::audio_sample_trigger )
528 {
529 	if (is_valid_sample_buf(m_decode_addr))
530 	{
531 		// Indicate that data has been decoded
532 		LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
533 		m_audio_buffer |= 0x8000;
534 
535 		// Set the CDIC interrupt line
536 		LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
537 		m_intreq_callback(ASSERT_LINE);
538 
539 		sample_trigger();
540 	}
541 	else
542 	{
543 		// Indicate that data has been decoded
544 		LOGMASKED(LOG_SAMPLES, "Flagging end of sample\n");
545 		m_audio_buffer |= 0x8000;
546 
547 		// Set the CDIC interrupt line
548 		//LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line to flag that sample decoding is done\n");
549 		//m_intreq_callback(ASSERT_LINE);
550 		m_z_buffer |= 1;
551 	}
552 }
553 
sample_trigger()554 void cdicdic_device::sample_trigger()
555 {
556 	LOGMASKED(LOG_SAMPLES, "sample_trigger with m_decode_addr == %04x\n", m_decode_addr);
557 
558 	bool decoding = true;
559 	bool had_valid_sample = false;
560 	m_decode_period = attotime::zero;
561 	//const uint16_t decode_start = m_decode_addr;
562 	do
563 	{
564 		const bool valid_sample = is_valid_sample_buf(m_decode_addr & 0x3ffe);
565 
566 		if (valid_sample)
567 		{
568 			had_valid_sample = true;
569 
570 			LOGMASKED(LOG_SAMPLES, "Hit audio_sample_trigger, with m_decode_addr == %04x, calling decode_audio_sector\n", m_decode_addr);
571 
572 			// Decode the data at Z+4, the same offset as a normal CD sector.
573 			decode_audio_sector(((uint8_t*)m_ram.get()) + (m_decode_addr & 0x3ffe) + 4, 1);
574 			play_audio_sector();
575 
576 			// Delay until sample completion before requesting more data
577 			LOGMASKED(LOG_SAMPLES, "Data is valid, setting up a new callback\n");
578 			m_decode_period += attotime::from_hz(sample_buf_freq(m_decode_addr & 0x3ffe)) * (18*28*2*sample_buf_size(m_decode_addr & 0x3ffe));
579 			//m_periodic_sample_timer[m_decode_addr == 0x2800 ? 0 : 1]->adjust(m_decode_period);
580 			m_audio_sample_timer->adjust(m_decode_period);
581 			//dmadac_enable(&dmadac[0], 2, 0);
582 
583 			m_decode_addr ^= 0x1a00;
584 			m_z_buffer ^= 0x1a00;
585 			LOGMASKED(LOG_SAMPLES, "Updated m_decode_addr, new value is %04x\n", m_decode_addr);
586 
587 			// Indicate that data has been decoded
588 			//LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
589 			//m_audio_buffer |= 0x8000;
590 
591 			// Set the CDIC interrupt line
592 			//LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
593 			//m_intreq_callback(ASSERT_LINE);
594 
595 			// Swap buffer positions to indicate our new buffer position at the next read
596 
597 			//if (m_decode_addr == decode_start)
598 			{
599 				decoding = false;
600 			}
601 		}
602 		else
603 		{
604 			LOGMASKED(LOG_SAMPLES, "Data is not valid, stopping playback\n");
605 			m_audio_sample_timer->adjust(attotime::never);
606 			decoding = false;
607 
608 			// Indicate that data has been decoded
609 			LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
610 			//m_audio_buffer |= 0x8000;
611 
612 			// Set the CDIC interrupt line
613 			LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
614 			m_intreq_callback(ASSERT_LINE);
615 
616 			m_z_buffer |= 1;
617 		}
618 	} while (decoding);
619 
620 	if (had_valid_sample)
621 	{
622 		//m_periodic_sample_timer->adjust(m_decode_period);
623 	}
624 }
625 
TIMER_CALLBACK_MEMBER(cdicdic_device::trigger_readback_int)626 TIMER_CALLBACK_MEMBER( cdicdic_device::trigger_readback_int )
627 {
628 	process_delayed_command();
629 }
630 
process_delayed_command()631 void cdicdic_device::process_delayed_command()
632 {
633 	switch (m_command)
634 	{
635 		case 0x23: // Reset Mode 1
636 		case 0x24: // Reset Mode 2
637 		case 0x29: // Read Mode 1
638 		case 0x2a: // Read Mode 2
639 		{
640 			static const char* const s_cmds[8] =
641 			{
642 				"Reset Mode 1",
643 				"Reset Mode 2", 0, 0, 0, 0,
644 				"Read Mode 1",
645 				"Read Mode 2"
646 			};
647 			uint8_t buffer[2560] = { 0 };
648 			uint32_t msf = m_time >> 8;
649 			LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command with MSF %06x: %s\n", machine().describe_context(), msf, s_cmds[m_command - 0x23]);
650 			uint8_t nybbles[6] =
651 			{
652 				static_cast<uint8_t>(msf & 0x0000000f),
653 				static_cast<uint8_t>((msf & 0x000000f0) >> 4),
654 				static_cast<uint8_t>((msf & 0x00000f00) >> 8),
655 				static_cast<uint8_t>((msf & 0x0000f000) >> 12),
656 				static_cast<uint8_t>((msf & 0x000f0000) >> 16),
657 				static_cast<uint8_t>((msf & 0x00f00000) >> 20)
658 			};
659 			if ((msf & 0x0000ff) >= 0x75)
660 			{
661 				LOGMASKED(LOG_COMMANDS, "%s: Weird frame timestamp detected: %02x\n", machine().describe_context(), (uint8_t)msf);
662 				msf &= 0xffff00;
663 				nybbles[0] = 0;
664 				nybbles[1] = 0;
665 			}
666 			if (nybbles[2] >= 2)
667 			{
668 				nybbles[2] -= 2;
669 			}
670 			else
671 			{
672 				nybbles[2] = 8 + nybbles[2];
673 				if (nybbles[3] > 0)
674 				{
675 					nybbles[3]--;
676 				}
677 				else
678 				{
679 					nybbles[3] = 5;
680 					if (nybbles[4] > 0)
681 					{
682 						nybbles[4]--;
683 					}
684 					else
685 					{
686 						nybbles[4] = 9;
687 						nybbles[5]--;
688 					}
689 				}
690 			}
691 			uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
692 
693 			LOGMASKED(LOG_COMMANDS, "%s: Reading Mode %d sector from MSF location %06x / %x%x%x%x%x%x, LBA %08x\n", machine().describe_context(), m_command - 0x28,
694 				(m_time >> 8) - 0x200, nybbles[5], nybbles[4], nybbles[3], nybbles[2], nybbles[1], nybbles[0], lba);
695 
696 			cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE);
697 
698 			m_time += 0x100;
699 			if ((m_time & 0x00000f00) == 0x00000a00)
700 			{
701 				m_time &= 0xfffff0ff;
702 				m_time += 0x00001000;
703 			}
704 			if ((m_time & 0x0000ff00) == 0x00007500)
705 			{
706 				m_time &= 0xffff00ff;
707 				m_time += 0x00010000;
708 				if ((m_time & 0x000f0000) == 0x000a0000)
709 				{
710 					m_time &= 0xfff0ffff;
711 					m_time += 0x00100000;
712 				}
713 			}
714 			if ((m_time & 0x00ff0000) == 0x00600000)
715 			{
716 				m_time &= 0xff00ffff;
717 				m_time += 0x01000000;
718 				if ((m_time & 0x0f000000) == 0x0a000000)
719 				{
720 					m_time &= 0xf0ffffff;
721 					m_time += 0x10000000;
722 				}
723 			}
724 
725 			m_data_buffer &= ~0x0004;
726 			m_data_buffer ^= 0x0001;
727 
728 			const bool file_match = (buffer[CDIC_SECTOR_FILE2] << 8) == m_file;
729 			const bool channel_match = (m_channel & (1 << buffer[CDIC_SECTOR_CHAN2])) != 0;
730 			const bool audio_channel_match = (m_audio_channel & (1 << buffer[CDIC_SECTOR_CHAN2])) != 0;
731 			const bool is_audio = (buffer[CDIC_SECTOR_SUBMODE2] & (CDIC_SUBMODE_FORM | CDIC_SUBMODE_DATA | CDIC_SUBMODE_AUDIO | CDIC_SUBMODE_VIDEO)) == (CDIC_SUBMODE_FORM | CDIC_SUBMODE_AUDIO);
732 			if (file_match)
733 			{
734 				if (is_audio && channel_match && audio_channel_match)
735 				{
736 					m_x_buffer |= 0x8000;
737 					//m_data_buffer |= 0x4000;
738 					m_data_buffer |= 4;
739 
740 					LOGMASKED(LOG_SECTORS, "%s: Audio sector into %04x\n", machine().describe_context(), (m_data_buffer & 5) * 0xa00);
741 
742 					for (int index = 6; index < 2352/2; index++)
743 					{
744 						m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
745 					}
746 
747 					decode_audio_sector(((uint8_t*)m_ram.get()) + ((m_data_buffer & 5) * 0xa00 + 4), 0);
748 
749 					LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for audio sector\n", machine().describe_context());
750 					//}
751 					m_intreq_callback(ASSERT_LINE);
752 					//else
753 					//{
754 					//  LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for ignored audio sector (m_channel %04x, m_audio_channel %04x, sector channel %04x\n",
755 					//      machine().describe_context(), m_channel, m_audio_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
756 					//  m_intreq_callback(ASSERT_LINE);
757 					//}
758 				}
759 				else if ((buffer[CDIC_SECTOR_SUBMODE2] & (CDIC_SUBMODE_DATA | CDIC_SUBMODE_AUDIO | CDIC_SUBMODE_VIDEO)) == 0x00)
760 				{
761 					m_x_buffer |= 0x8000;
762 					//m_data_buffer |= 0x4000;
763 
764 					for (int index = 6; index < 2352/2; index++)
765 					{
766 						m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
767 					}
768 
769 					if ((buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_TRIG) == CDIC_SUBMODE_TRIG ||
770 						(buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOR) == CDIC_SUBMODE_EOR ||
771 						(buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) == CDIC_SUBMODE_EOF)
772 					{
773 						LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for message sector\n", machine().describe_context());
774 						m_intreq_callback(ASSERT_LINE);
775 					}
776 					else
777 					{
778 						LOGMASKED(LOG_SECTORS, "%s: Setting CDIC interrupt line for ignored message sector\n", machine().describe_context());
779 						m_intreq_callback(ASSERT_LINE);
780 					}
781 				}
782 				else if (channel_match)
783 				{
784 					m_x_buffer |= 0x8000;
785 					//m_data_buffer |= 0x4000;
786 
787 					if (is_audio)
788 					{
789 						//m_data_buffer |= 4;
790 						//m_z_buffer = (m_data_buffer & 5) * 0xa00;
791 					}
792 
793 					for (int index = 6; index < 2352/2; index++)
794 					{
795 						m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
796 					}
797 
798 					LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for data sector to %04x, submode 2 flags are:\n", machine().describe_context(), (m_data_buffer & 5) * 0xa00);
799 					LOGMASKED(LOG_IRQS, "%s: Channel reg is: %08x, versus submode channel: %08x\n", machine().describe_context(), m_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
800 					if (!BIT(m_channel, buffer[CDIC_SECTOR_CHAN2]))
801 					{
802 						LOGMASKED(LOG_IRQS, "%s: Channel mismatch\n", machine().describe_context());
803 						m_intreq_callback(ASSERT_LINE);
804 					}
805 					else
806 					{
807 						m_intreq_callback(ASSERT_LINE);
808 					}
809 					const uint16_t submode2 = buffer[CDIC_SECTOR_SUBMODE2];
810 					if (submode2 & CDIC_SUBMODE_EOF)   LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOF\n", machine().describe_context());
811 					if (submode2 & CDIC_SUBMODE_RT)    LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_RT\n", machine().describe_context());
812 					if (submode2 & CDIC_SUBMODE_FORM)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_FORM\n", machine().describe_context());
813 					if (submode2 & CDIC_SUBMODE_TRIG)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_TRIG\n", machine().describe_context());
814 					if (submode2 & CDIC_SUBMODE_DATA)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_DATA\n", machine().describe_context());
815 					if (submode2 & CDIC_SUBMODE_AUDIO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_AUDIO\n", machine().describe_context());
816 					if (submode2 & CDIC_SUBMODE_VIDEO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_VIDEO\n", machine().describe_context());
817 					if (submode2 & CDIC_SUBMODE_EOR)   LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOR\n", machine().describe_context());
818 				}
819 				else
820 				{
821 					//m_x_buffer |= 0x8000;
822 
823 					LOGMASKED(LOG_IRQS, "%s: No match: m_channel %04x, m_audio_channel %04x, sector channel %04x\n",
824 						machine().describe_context(), m_channel, m_audio_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
825 					const uint16_t submode2 = buffer[CDIC_SECTOR_SUBMODE2];
826 					if (submode2 & CDIC_SUBMODE_EOF)   LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOF\n", machine().describe_context());
827 					if (submode2 & CDIC_SUBMODE_RT)    LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_RT\n", machine().describe_context());
828 					if (submode2 & CDIC_SUBMODE_FORM)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_FORM\n", machine().describe_context());
829 					if (submode2 & CDIC_SUBMODE_TRIG)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_TRIG\n", machine().describe_context());
830 					if (submode2 & CDIC_SUBMODE_DATA)  LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_DATA\n", machine().describe_context());
831 					if (submode2 & CDIC_SUBMODE_AUDIO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_AUDIO\n", machine().describe_context());
832 					if (submode2 & CDIC_SUBMODE_VIDEO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_VIDEO\n", machine().describe_context());
833 					if (submode2 & CDIC_SUBMODE_EOR)   LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOR\n", machine().describe_context());
834 					//m_intreq_callback(ASSERT_LINE);
835 				}
836 
837 				if ((buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) == 0 && m_command != 0x23)
838 				{
839 					LOGMASKED(LOG_IRQS, "Setting CDIC processing to trigger in 75Hz due to non-EOF.\n");
840 					m_interrupt_timer->adjust(attotime::from_hz(75)); // 75Hz = 1x CD-ROM speed
841 				}
842 				else
843 				{
844 					LOGMASKED(LOG_IRQS, "Not setting CDIC processing, EOF is %d\n", (buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) ? 1 : 0);
845 					m_interrupt_timer->adjust(attotime::never);
846 					//m_data_buffer &= ~0x4000;
847 					//m_interrupt_timer->adjust(attotime::from_hz(75));
848 				}
849 			}
850 			else
851 			{
852 				LOGMASKED(LOG_IRQS, "File mismatch\n");
853 			}
854 			break;
855 		}
856 
857 		case 0x2e: // Abort
858 			LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Abort\n", machine().describe_context());
859 			m_interrupt_timer->adjust(attotime::never);
860 			//m_data_buffer &= ~4;
861 			break;
862 
863 		case 0x28: // Play CDDA audio
864 		{
865 			LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Play CDDA Audio\n", machine().describe_context());
866 			uint8_t buffer[2560] = { 0 };
867 			uint32_t msf = (m_time & 0xffff7f00) >> 8;
868 			uint32_t next_msf = increment_cdda_frame_bcd((m_time & 0xffff7f00) >> 8);
869 			uint32_t rounded_next_msf = increment_cdda_sector_bcd((m_time & 0xffff0000) >> 8);
870 			uint8_t nybbles[6] =
871 			{
872 				static_cast<uint8_t>(msf & 0x0000000f),
873 				static_cast<uint8_t>((msf & 0x000000f0) >> 4),
874 				static_cast<uint8_t>((msf & 0x00000f00) >> 8),
875 				static_cast<uint8_t>((msf & 0x0000f000) >> 12),
876 				static_cast<uint8_t>((msf & 0x000f0000) >> 16),
877 				static_cast<uint8_t>((msf & 0x00f00000) >> 20)
878 			};
879 
880 			uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
881 
882 			if (!cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE))
883 			{
884 				osd_printf_verbose("Unable to read CD-ROM data.\n", machine().describe_context());
885 			}
886 
887 			if (!(msf & 0x0000ff))
888 			{
889 				LOGMASKED(LOG_COMMANDS, "%s: Playing CDDA sector from MSF location %06x\n", machine().describe_context(), m_time | 2);
890 				m_cdda->start_audio(lba, rounded_next_msf);
891 			}
892 
893 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x924/2] = 0x0001;                      //  CTRL
894 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x926/2] = 0x0001;                      //  TRACK
895 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x928/2] = 0x0000;                      //  INDEX
896 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92a/2] = (m_time >> 24) & 0x000000ff; //  MIN
897 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92c/2] = (m_time >> 16) & 0x000000ff; //  SEC
898 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92e/2] = (m_time >>  8) & 0x0000007f; //  FRAC
899 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x930/2] = 0x0000;                      //  ZERO
900 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x932/2] = (m_time >> 24) & 0x000000ff; //  AMIN
901 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x934/2] = (m_time >> 16) & 0x000000ff; //  ASEC
902 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x936/2] = (m_time >>  8) & 0x0000007f; //  AFRAC
903 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x938/2] = 0x0000;                      //  CRC1
904 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x93a/2] = 0x0000;                      //  CRC2
905 
906 			m_time = next_msf << 8;
907 
908 			// the following line BREAKS 'The Apprentice', hangs when you attempt to start the game
909 			//m_interrupt_timer->adjust(attotime::from_hz(75));
910 
911 			m_x_buffer |= 0x8000;
912 			//m_data_buffer |= 0x4000;
913 
914 			for (int index = 6; index < 2352/2; index++)
915 			{
916 				m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
917 			}
918 
919 			LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for CDDA sector\n", machine().describe_context());
920 			m_intreq_callback(ASSERT_LINE);
921 			break;
922 		}
923 		case 0x2c: // Seek
924 		{
925 			LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Seek\n", machine().describe_context());
926 			uint8_t buffer[2560] = { 0 };
927 			uint32_t msf = (m_time & 0xffff7f00) >> 8;
928 			uint32_t next_msf = increment_cdda_frame_bcd((m_time & 0xffff7f00) >> 8);
929 			uint8_t nybbles[6] =
930 			{
931 				static_cast<uint8_t>(msf & 0x0000000f),
932 				static_cast<uint8_t>((msf & 0x000000f0) >> 4),
933 				static_cast<uint8_t>((msf & 0x00000f00) >> 8),
934 				static_cast<uint8_t>((msf & 0x0000f000) >> 12),
935 				static_cast<uint8_t>((msf & 0x000f0000) >> 16),
936 				static_cast<uint8_t>((msf & 0x00f00000) >> 20)
937 			};
938 			uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
939 
940 			m_interrupt_timer->adjust(attotime::from_hz(75));
941 
942 			cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE);
943 
944 			m_data_buffer ^= 0x0001;
945 			m_x_buffer |= 0x8000;
946 			m_data_buffer |= 0x4000;
947 
948 			for (int index = 6; index < 2352/2; index++)
949 			{
950 				m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
951 			}
952 
953 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x924/2] = 0x0041;                      //  CTRL
954 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x926/2] = 0x0001;                      //  TRACK
955 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x928/2] = 0x0000;                      //  INDEX
956 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92a/2] = (m_time >> 24) & 0x000000ff; //  MIN
957 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92c/2] = (m_time >> 16) & 0x000000ff; //  SEC
958 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92e/2] = (m_time >>  8) & 0x0000007f; //  FRAC
959 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x930/2] = 0x0000;                      //  ZERO
960 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x932/2] = (m_time >> 24) & 0x000000ff; //  AMIN
961 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x934/2] = (m_time >> 16) & 0x000000ff; //  ASEC
962 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x936/2] = (m_time >>  8) & 0x0000007f; //  AFRAC
963 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x938/2] = 0x0000;                      //  CRC1
964 			m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x93a/2] = 0x0000;                      //  CRC2
965 
966 			m_time = next_msf << 8;
967 
968 			LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for Seek sector\n", machine().describe_context());
969 			m_intreq_callback(ASSERT_LINE);
970 			break;
971 		}
972 	}
973 }
974 
regs_r(offs_t offset,uint16_t mem_mask)975 uint16_t cdicdic_device::regs_r(offs_t offset, uint16_t mem_mask)
976 {
977 	uint32_t addr = offset + 0x3c00/2;
978 
979 	switch (addr)
980 	{
981 		case 0x3c00/2: // Command register
982 			LOGMASKED(LOG_READS, "%s: cdic_r: Command Register = %04x & %04x\n", machine().describe_context(), m_command, mem_mask);
983 			return m_command;
984 
985 		case 0x3c02/2: // Time register (MSW)
986 			LOGMASKED(LOG_READS, "%s: cdic_r: Time Register (MSW) = %04x & %04x\n", machine().describe_context(), m_time >> 16, mem_mask);
987 			return m_time >> 16;
988 
989 		case 0x3c04/2: // Time register (LSW)
990 			LOGMASKED(LOG_READS, "%s: cdic_r: Time Register (LSW) = %04x & %04x\n", machine().describe_context(), (uint16_t)(m_time & 0x0000ffff), mem_mask);
991 			return m_time & 0x0000ffff;
992 
993 		case 0x3c06/2: // File register
994 			LOGMASKED(LOG_READS, "%s: cdic_r: File Register = %04x & %04x\n", machine().describe_context(), m_file, mem_mask);
995 			return m_file;
996 
997 		case 0x3c08/2: // Channel register (MSW)
998 			LOGMASKED(LOG_READS, "%s: cdic_r: Channel Register (MSW) = %04x & %04x\n", machine().describe_context(), m_channel >> 16, mem_mask);
999 			return m_channel >> 16;
1000 
1001 		case 0x3c0a/2: // Channel register (LSW)
1002 			LOGMASKED(LOG_READS, "%s: cdic_r: Channel Register (LSW) = %04x & %04x\n", machine().describe_context(), m_channel & 0x0000ffff, mem_mask);
1003 			return m_channel & 0x0000ffff;
1004 
1005 		case 0x3c0c/2: // Audio Channel register
1006 			LOGMASKED(LOG_READS, "%s: cdic_r: Audio Channel Register = %04x & %04x\n", machine().describe_context(), m_audio_channel, mem_mask);
1007 			if (m_break_on_achan)
1008 			{
1009 				machine().debug_break();
1010 			}
1011 			return m_audio_channel;
1012 
1013 		case 0x3ff4/2: // ABUF
1014 		{
1015 			uint16_t temp = m_audio_buffer;
1016 			LOGMASKED(LOG_READS, "%s: cdic_r: Audio Buffer Register = %04x & %04x\n", machine().describe_context(), temp, mem_mask);
1017 			m_audio_buffer &= 0x7fff;
1018 			if (!((m_audio_buffer | m_x_buffer) & 0x8000))
1019 			{
1020 				m_intreq_callback(CLEAR_LINE);
1021 				LOGMASKED(LOG_IRQS, "%s: Clearing CDIC interrupt line\n", machine().describe_context());
1022 			}
1023 			return temp;
1024 		}
1025 
1026 		case 0x3ff6/2: // XBUF
1027 		{
1028 			uint16_t temp = m_x_buffer;
1029 			LOGMASKED(LOG_READS, "%s: cdic_r: X-Buffer Register = %04x & %04x\n", machine().describe_context(), temp, mem_mask);
1030 			m_x_buffer &= 0x7fff;
1031 			if (!((m_audio_buffer | m_x_buffer) & 0x8000))
1032 			{
1033 				m_intreq_callback(CLEAR_LINE);
1034 				LOGMASKED(LOG_IRQS, "%s: Clearing CDIC interrupt line\n", machine().describe_context());
1035 			}
1036 			return temp;
1037 		}
1038 
1039 		case 0x3ffa/2: // AUDCTL
1040 		{
1041 			LOGMASKED(LOG_READS, "%s: cdic_r: Z-Buffer Register Read: %04x & %04x\n", machine().describe_context(), m_z_buffer, mem_mask);
1042 			if (m_audio_playback_timer->remaining().is_never() && m_audio_sample_timer->remaining().is_never())
1043 			{
1044 				return m_z_buffer | 1;
1045 			}
1046 			return m_z_buffer;
1047 		}
1048 
1049 		case 0x3ffe/2:
1050 		{
1051 			LOGMASKED(LOG_READS, "%s: cdic_r: Data buffer Register = %04x & %04x\n", machine().describe_context(), m_data_buffer, mem_mask);
1052 			return m_data_buffer;
1053 		}
1054 		default:
1055 			LOGMASKED(LOG_READS | LOG_UNKNOWNS, "%s: cdic_r: Unknown address: %04x & %04x\n", machine().describe_context(), addr*2, mem_mask);
1056 			return 0;
1057 	}
1058 }
1059 
regs_w(offs_t offset,uint16_t data,uint16_t mem_mask)1060 void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
1061 {
1062 	uint32_t addr = offset + 0x3c00/2;
1063 
1064 	switch (addr)
1065 	{
1066 		case 0x3c00/2: // Command register
1067 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Command Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1068 			COMBINE_DATA(&m_command);
1069 			break;
1070 
1071 		case 0x3c02/2: // Time register (MSW)
1072 			m_time &= ~(mem_mask << 16);
1073 			m_time |= (data & mem_mask) << 16;
1074 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Time Register (MSW) = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1075 			break;
1076 
1077 		case 0x3c04/2: // Time register (LSW)
1078 			m_time &= ~mem_mask;
1079 			m_time |= data & mem_mask;
1080 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Time Register (LSW) = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1081 			break;
1082 
1083 		case 0x3c06/2: // File register
1084 			LOGMASKED(LOG_WRITES, "%s: cdic_w: File Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1085 			COMBINE_DATA(&m_file);
1086 			break;
1087 
1088 		case 0x3c08/2: // Channel register (MSW)
1089 			m_channel &= ~(mem_mask << 16);
1090 			m_channel |= (data & mem_mask) << 16;
1091 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Channel Register (MSW) = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1092 			break;
1093 
1094 		case 0x3c0a/2: // Channel register (LSW)
1095 			m_channel &= ~mem_mask;
1096 			m_channel |= data & mem_mask;
1097 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Channel Register (LSW) = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1098 			break;
1099 
1100 		case 0x3c0c/2: // Audio Channel register
1101 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Audio Channel Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1102 			COMBINE_DATA(&m_audio_channel);
1103 			break;
1104 
1105 		case 0x3ff4/2:
1106 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Audio Buffer Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1107 			COMBINE_DATA(&m_audio_buffer);
1108 			break;
1109 
1110 		case 0x3ff6/2:
1111 			LOGMASKED(LOG_WRITES, "%s: cdic_w: X Buffer Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1112 			COMBINE_DATA(&m_x_buffer);
1113 			break;
1114 
1115 		case 0x3ff8/2:
1116 		{
1117 			uint32_t start = m_scc->dma().channel[0].memory_address_counter;
1118 			uint32_t count = m_scc->dma().channel[0].transfer_counter;
1119 			uint32_t device_index = (data & 0x3fff) >> 1;
1120 			LOGMASKED(LOG_WRITES, "%s: cdic_w: DMA Control Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1121 			LOGMASKED(LOG_WRITES, "%s: Memory address counter: %08x\n", machine().describe_context(), m_scc->dma().channel[0].memory_address_counter);
1122 			LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & OCR_D) ? "to main RAM" : "to device RAM");
1123 			printf("\n");
1124 			for (uint32_t index = start / 2; index < (start / 2 + count); index++)
1125 			{
1126 				if (m_scc->dma().channel[0].operation_control & OCR_D)
1127 				{
1128 					m_memory_space->write_word(index * 2, m_ram[device_index++]);
1129 				}
1130 				else
1131 				{
1132 					m_ram[device_index++] = m_memory_space->read_word(index * 2);
1133 				}
1134 			}
1135 			m_scc->dma().channel[0].memory_address_counter += m_scc->dma().channel[0].transfer_counter * 2;
1136 			break;
1137 		}
1138 
1139 		case 0x3ffa/2:
1140 		{
1141 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Z-Buffer Register Write: %04x & %04x\n", machine().describe_context(), data, mem_mask);
1142 			COMBINE_DATA(&m_z_buffer);
1143 			if (m_z_buffer & 0x2000)
1144 			{
1145 				//if (m_audio_sample_timer->remaining().is_never())
1146 				{
1147 					m_decode_addr = m_z_buffer & 0x3a00;
1148 					LOGMASKED(LOG_WRITES, "%s: New decode address: %04x\n", machine().describe_context(), m_decode_addr);
1149 					m_audio_playback_timer->adjust(attotime::from_hz(1000));
1150 					//m_decode_delay = 1;
1151 					//m_audio_sample_timer->adjust(attotime::from_hz(75));
1152 				}
1153 			}
1154 			else
1155 			{
1156 				m_decode_addr = 0xffff;
1157 				m_audio_sample_timer->adjust(attotime::never);
1158 				m_periodic_sample_timer[0]->adjust(attotime::never);
1159 				m_periodic_sample_timer[1]->adjust(attotime::never);
1160 			}
1161 			break;
1162 		}
1163 
1164 		case 0x3ffc/2:
1165 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Interrupt Vector Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1166 			COMBINE_DATA(&m_interrupt_vector);
1167 			break;
1168 
1169 		case 0x3ffe/2:
1170 		{
1171 			LOGMASKED(LOG_WRITES, "%s: cdic_w: Data Buffer Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
1172 			COMBINE_DATA(&m_data_buffer);
1173 			if (m_data_buffer & 0x8000)
1174 			{
1175 				m_audio_sample_timer->adjust(attotime::never);
1176 				m_audio_playback_timer->adjust(attotime::never);
1177 				m_periodic_sample_timer[0]->adjust(attotime::never);
1178 				m_periodic_sample_timer[1]->adjust(attotime::never);
1179 				LOGMASKED(LOG_WRITES, "%s: cdic_w: Data Buffer high-bit set, beginning command processing\n", machine().describe_context());
1180 				switch (m_command)
1181 				{
1182 					case 0x23: // Reset Mode 1
1183 					case 0x24: // Reset Mode 2
1184 						LOGMASKED(LOG_WRITES, "%s: cdic_w: Reset Mode %d command\n", machine().describe_context(), m_command - 0x22);
1185 						m_interrupt_timer->adjust(attotime::never);
1186 						m_dmadac[0]->enable(0);
1187 						m_dmadac[1]->enable(0);
1188 						m_data_buffer &= 0x7fff;
1189 						break;
1190 					case 0x2e: // Abort
1191 						LOGMASKED(LOG_WRITES, "%s: cdic_w: Abort command\n", machine().describe_context());
1192 						m_interrupt_timer->adjust(attotime::never);
1193 						//m_audio_sample_timer->adjust(attotime::never);
1194 						//m_periodic_sample_timer->adjust(attotime::never);
1195 						m_dmadac[0]->enable(0);
1196 						m_dmadac[1]->enable(0);
1197 						m_data_buffer &= 0x3fff;
1198 						break;
1199 					case 0x2b: // Stop CDDA
1200 						LOGMASKED(LOG_WRITES, "%s: cdic_w: Stop CDDA\n", machine().describe_context());
1201 						m_cdda->stop_audio();
1202 						m_interrupt_timer->adjust(attotime::never);
1203 						m_data_buffer &= 0x7fff;
1204 						break;
1205 					case 0x29: // Read Mode 1
1206 					case 0x2a: // Read Mode 2
1207 					case 0x28: // Play CDDA
1208 					case 0x2c: // Seek
1209 					{
1210 						attotime period = m_interrupt_timer->remaining();
1211 						if (!period.is_never())
1212 						{
1213 							LOGMASKED(LOG_WRITES, "%s: cdic_w: Other command (%02x), interrupt in-flight, letting it ride\n", machine().describe_context(), m_command);
1214 							m_interrupt_timer->adjust(period);
1215 						}
1216 						else
1217 						{
1218 							LOGMASKED(LOG_WRITES, "%s: cdic_w: Other command (%02x), interrupt not in-flight, interrupting in 75Hz\n", machine().describe_context(), m_command);
1219 							m_interrupt_timer->adjust(attotime::from_hz(75));
1220 						}
1221 						m_data_buffer &= 0x7fff;
1222 						break;
1223 					}
1224 					default:
1225 						LOGMASKED(LOG_COMMANDS, "%s: Unknown CDIC command: %02x\n", machine().describe_context(), m_command);
1226 						break;
1227 				}
1228 			}
1229 			break;
1230 		}
1231 		default:
1232 			LOGMASKED(LOG_WRITES | LOG_UNKNOWNS, "%s: cdic_w: Unknown address: %04x = %04x & %04x\n", machine().describe_context(), addr*2, data, mem_mask);
1233 			break;
1234 	}
1235 }
1236 
1237 //**************************************************************************
1238 //  LIVE DEVICE
1239 //**************************************************************************
1240 
1241 //-------------------------------------------------
1242 //  cdicdic_device - constructor
1243 //-------------------------------------------------
1244 
cdicdic_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1245 cdicdic_device::cdicdic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1246 	: device_t(mconfig, CDI_CDIC, tag, owner, clock)
1247 	, m_intreq_callback(*this)
1248 	, m_memory_space(*this, ":maincpu", AS_PROGRAM)
1249 	, m_dmadac(*this, ":dac%u", 1U)
1250 	, m_scc(*this, ":maincpu")
1251 	, m_cdda(*this, ":cdda")
1252 	, m_cdrom_dev(*this, ":cdrom")
1253 	, m_clock2(clock)
1254 {
1255 }
1256 
1257 //-------------------------------------------------
1258 //  device_resolve_objects - resolve objects that
1259 //  may be needed for other devices to set
1260 //  initial conditions at start time
1261 //-------------------------------------------------
1262 
device_resolve_objects()1263 void cdicdic_device::device_resolve_objects()
1264 {
1265 	m_intreq_callback.resolve_safe();
1266 }
1267 
1268 //-------------------------------------------------
1269 //  device_start - device-specific startup
1270 //-------------------------------------------------
1271 
device_start()1272 void cdicdic_device::device_start()
1273 {
1274 	save_item(NAME(m_command));
1275 	save_item(NAME(m_time));
1276 	save_item(NAME(m_file));
1277 	save_item(NAME(m_channel));
1278 	save_item(NAME(m_audio_channel));
1279 	save_item(NAME(m_audio_buffer));
1280 	save_item(NAME(m_x_buffer));
1281 	save_item(NAME(m_dma_control));
1282 	save_item(NAME(m_z_buffer));
1283 	save_item(NAME(m_interrupt_vector));
1284 	save_item(NAME(m_data_buffer));
1285 
1286 	save_item(NAME(m_audio_sample_freq));
1287 	save_item(NAME(m_audio_sample_size));
1288 
1289 	m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::trigger_readback_int), this));
1290 	m_interrupt_timer->adjust(attotime::never);
1291 
1292 	m_audio_sample_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::audio_sample_trigger), this));
1293 	m_audio_sample_timer->adjust(attotime::never);
1294 
1295 	m_audio_playback_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::initial_sample_trigger), this));
1296 	m_audio_playback_timer->adjust(attotime::never);
1297 
1298 	m_periodic_sample_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::periodic_sample_trigger), this));
1299 	m_periodic_sample_timer[0]->adjust(attotime::never);
1300 	m_periodic_sample_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::periodic_sample_trigger), this));
1301 	m_periodic_sample_timer[1]->adjust(attotime::never);
1302 
1303 	m_ram = std::make_unique<uint16_t[]>(0x3c00/2);
1304 	m_samples[0] = std::make_unique<int16_t[]>(18*28*16+16);
1305 	m_samples[1] = std::make_unique<int16_t[]>(18*28*16+16);
1306 }
1307 
1308 //-------------------------------------------------
1309 //  device_reset - device-specific reset
1310 //-------------------------------------------------
1311 
device_reset()1312 void cdicdic_device::device_reset()
1313 {
1314 	m_command = 0;
1315 	m_time = 0;
1316 	m_file = 0;
1317 	m_channel = 0xffffffff;
1318 	m_audio_channel = 0xffff;
1319 	m_audio_buffer = 0;
1320 	m_x_buffer = 0;
1321 	m_dma_control = 0;
1322 	m_z_buffer = 0;
1323 	m_interrupt_vector = 0x0f;
1324 	m_data_buffer = 0;
1325 
1326 	m_audio_sample_freq = 0;
1327 	m_audio_sample_size = 0;
1328 
1329 	m_decode_addr = 0;
1330 	m_decode_delay = 0;
1331 
1332 	if (m_cdrom_dev)
1333 	{
1334 		// MESS case (has CDROM device)
1335 		m_cd = m_cdrom_dev->get_cdrom_file();
1336 		m_cdda->set_cdrom(m_cd);
1337 	}
1338 	else
1339 	{
1340 		// MAME case
1341 		m_cd = cdrom_open(machine().rom_load().get_disk_handle(":cdrom"));
1342 		m_cdda->set_cdrom(m_cd);
1343 	}
1344 
1345 	m_interrupt_timer->adjust(attotime::never);
1346 	m_audio_sample_timer->adjust(attotime::never);
1347 	m_audio_playback_timer->adjust(attotime::never);
1348 	m_periodic_sample_timer[0]->adjust(attotime::never);
1349 	m_periodic_sample_timer[1]->adjust(attotime::never);
1350 
1351 	m_break_on_achan = false;
1352 	m_valid_audio_sample = false;
1353 
1354 	m_intreq_callback(CLEAR_LINE);
1355 }
1356 
ram_w(offs_t offset,uint16_t data,uint16_t mem_mask)1357 void cdicdic_device::ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
1358 {
1359 	LOGMASKED(LOG_RAM, "%s: ram_w: %04x = %04x & %04x\n", machine().describe_context(), offset << 1, data, mem_mask);
1360 	COMBINE_DATA(&m_ram[offset]);
1361 }
1362 
ram_r(offs_t offset,uint16_t mem_mask)1363 uint16_t cdicdic_device::ram_r(offs_t offset, uint16_t mem_mask)
1364 {
1365 	LOGMASKED(LOG_RAM, "%s: ram_r: %04x : %04x & %04x\n", machine().describe_context(), offset << 1, m_ram[offset], mem_mask);
1366 	return m_ram[offset];
1367 }
1368 
intack_r()1369 uint8_t cdicdic_device::intack_r()
1370 {
1371 	return m_interrupt_vector & 0xff;
1372 }
1373