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