Mercurial > repos > blastem
comparison cdd_mcu.c @ 2080:bafb757e1cd2
Implement CD audio
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 02 Feb 2022 01:10:07 -0800 |
parents | 5a2b759f6b2d |
children | cfd53c94fffb |
comparison
equal
deleted
inserted
replaced
2079:5a2b759f6b2d | 2080:bafb757e1cd2 |
---|---|
37 void cdd_mcu_init(cdd_mcu *context, system_media *media) | 37 void cdd_mcu_init(cdd_mcu *context, system_media *media) |
38 { | 38 { |
39 context->next_int_cycle = CYCLE_NEVER; | 39 context->next_int_cycle = CYCLE_NEVER; |
40 context->last_subcode_cycle = CYCLE_NEVER; | 40 context->last_subcode_cycle = CYCLE_NEVER; |
41 context->last_nibble_cycle = CYCLE_NEVER; | 41 context->last_nibble_cycle = CYCLE_NEVER; |
42 context->last_byte_cycle = CYCLE_NEVER; | 42 context->last_byte_cycle = 0; |
43 context->requested_format = SF_NOTREADY; | 43 context->requested_format = SF_NOTREADY; |
44 context->media = media; | 44 context->media = media; |
45 context->current_status_nibble = -1; | 45 context->current_status_nibble = -1; |
46 context->current_cmd_nibble = -1; | 46 context->current_cmd_nibble = -1; |
47 context->current_sector_byte = -1; | 47 context->current_sector_byte = -1; |
50 enum { | 50 enum { |
51 GAO_CDD_CTRL, | 51 GAO_CDD_CTRL, |
52 GAO_CDD_STATUS, | 52 GAO_CDD_STATUS, |
53 GAO_CDD_CMD = GAO_CDD_STATUS+5 | 53 GAO_CDD_CMD = GAO_CDD_STATUS+5 |
54 }; | 54 }; |
55 //GAO_CDD_CTRL | |
56 #define BIT_MUTE 0x100 | |
57 #define BIT_HOCK 0x0004 | |
58 #define BIT_DRS 0x0002 | |
59 #define BIT_DTS 0x0001 | |
55 | 60 |
56 static uint8_t checksum(uint8_t *vbuffer) | 61 static uint8_t checksum(uint8_t *vbuffer) |
57 { | 62 { |
58 uint8_t *buffer = vbuffer; | 63 uint8_t *buffer = vbuffer; |
59 uint8_t sum = 0; | 64 uint8_t sum = 0; |
103 context->status_buffer.b.time.sec_low = seconds % 10; | 108 context->status_buffer.b.time.sec_low = seconds % 10; |
104 context->status_buffer.b.time.frame_high = frames / 10; | 109 context->status_buffer.b.time.frame_high = frames / 10; |
105 context->status_buffer.b.time.frame_low = frames % 10; | 110 context->status_buffer.b.time.frame_low = frames % 10; |
106 } | 111 } |
107 | 112 |
108 static void update_status(cdd_mcu *context) | 113 static void update_status(cdd_mcu *context, uint16_t *gate_array) |
109 { | 114 { |
115 gate_array[GAO_CDD_CTRL] |= BIT_MUTE; | |
110 switch (context->status) | 116 switch (context->status) |
111 { | 117 { |
112 case DS_PLAY: | 118 case DS_PLAY: |
113 handle_seek(context); | 119 handle_seek(context); |
114 if (!context->seeking) { | 120 if (!context->seeking) { |
115 context->head_pba++; | 121 context->head_pba++; |
116 context->media->seek(context->media, context->head_pba - LEADIN_SECTORS); | 122 uint8_t track = context->media->seek(context->media, context->head_pba - LEADIN_SECTORS); |
123 if (context->media->tracks[track].type == TRACK_AUDIO) { | |
124 gate_array[GAO_CDD_CTRL] &= ~BIT_MUTE; | |
125 } | |
117 } | 126 } |
118 break; | 127 break; |
119 case DS_PAUSE: | 128 case DS_PAUSE: |
120 handle_seek(context); | 129 handle_seek(context); |
121 break; | 130 break; |
285 context->status_buffer.status = context->error_status; | 294 context->status_buffer.status = context->error_status; |
286 context->status_buffer.format = SF_NOTREADY; | 295 context->status_buffer.format = SF_NOTREADY; |
287 context->error_status = DS_STOP; | 296 context->error_status = DS_STOP; |
288 } | 297 } |
289 if (context->requested_format != SF_TOCN) { | 298 if (context->requested_format != SF_TOCN) { |
290 context->status_buffer.b.time.flags = 1; //TODO: populate these | 299 context->status_buffer.b.time.flags = !!(gate_array[GAO_CDD_CTRL] & BIT_MUTE); //TODO: populate these |
291 } | 300 } |
292 } else { | 301 } else { |
293 // Did not receive our first command so just send zeroes | 302 // Did not receive our first command so just send zeroes |
294 memset(&context->status_buffer, 0, sizeof(context->status_buffer) - 1); | 303 memset(&context->status_buffer, 0, sizeof(context->status_buffer) - 1); |
295 } | 304 } |
430 default: | 439 default: |
431 printf("CDD CMD: Unimplemented(%d)\n", context->cmd_buffer.cmd_type); | 440 printf("CDD CMD: Unimplemented(%d)\n", context->cmd_buffer.cmd_type); |
432 } | 441 } |
433 } | 442 } |
434 | 443 |
435 #define BIT_HOCK 0x4 | 444 void cdd_mcu_run(cdd_mcu *context, uint32_t cycle, uint16_t *gate_array, lc8951* cdc, cdd_fader* fader) |
436 #define BIT_DRS 0x2 | |
437 #define BIT_DTS 0x1 | |
438 | |
439 void cdd_mcu_run(cdd_mcu *context, uint32_t cycle, uint16_t *gate_array, lc8951* cdc) | |
440 { | 445 { |
441 uint32_t cd_cycle = mclks_to_cd_block(cycle); | 446 uint32_t cd_cycle = mclks_to_cd_block(cycle); |
447 uint32_t next_byte = context->last_byte_cycle + BYTE_CLOCKS; | |
442 if (!(gate_array[GAO_CDD_CTRL] & BIT_HOCK)) { | 448 if (!(gate_array[GAO_CDD_CTRL] & BIT_HOCK)) { |
443 //it's a little unclear if this gates the actual cd block clock or just handshaking | 449 //it's a little unclear if this gates the actual cd block clock or just handshaking |
444 //assum it's actually the clock for now | 450 //assum it's actually the clock for now |
445 context->cycle = cd_cycle; | 451 for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER) { |
452 if (context->cycle >= next_byte) { | |
453 cdd_fader_data(fader, 0); | |
454 next_byte = context->cycle + BYTE_CLOCKS; | |
455 context->last_byte_cycle = context->cycle; | |
456 } | |
457 } | |
458 gate_array[GAO_CDD_CTRL] |= BIT_MUTE; | |
446 return; | 459 return; |
447 } | 460 } |
448 uint32_t next_subcode = context->last_subcode_cycle + SECTOR_CLOCKS; | 461 uint32_t next_subcode = context->last_subcode_cycle + SECTOR_CLOCKS; |
449 uint32_t next_nibble = context->current_status_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; | 462 uint32_t next_nibble = context->current_status_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; |
450 uint32_t next_cmd_nibble = context->current_cmd_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; | 463 uint32_t next_cmd_nibble = context->current_cmd_nibble >= 0 ? context->last_nibble_cycle + NIBBLE_CLOCKS : CYCLE_NEVER; |
451 uint32_t next_byte = context->current_sector_byte >= 0 ? context->last_byte_cycle + BYTE_CLOCKS : CYCLE_NEVER; | 464 |
452 for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER) | 465 for (; context->cycle < cd_cycle; context->cycle += CDD_MCU_DIVIDER) |
453 { | 466 { |
454 if (context->cycle >= next_subcode) { | 467 if (context->cycle >= next_subcode) { |
455 context->last_subcode_cycle = context->cycle; | 468 context->last_subcode_cycle = context->cycle; |
456 next_subcode = context->cycle + SECTOR_CLOCKS; | 469 next_subcode = context->cycle + SECTOR_CLOCKS; |
457 update_status(context); | 470 update_status(context, gate_array); |
458 next_nibble = context->cycle; | 471 next_nibble = context->cycle; |
459 context->current_status_nibble = 0; | 472 context->current_status_nibble = 0; |
460 gate_array[GAO_CDD_STATUS] |= BIT_DRS; | 473 gate_array[GAO_CDD_STATUS] |= BIT_DRS; |
461 if (context->status == DS_PLAY && !context->seeking) { | 474 if (context->status == DS_PLAY && !context->seeking) { |
462 next_byte = context->cycle; | |
463 context->current_sector_byte = 0; | 475 context->current_sector_byte = 0; |
464 } | 476 } |
465 } | 477 } |
466 if (context->cycle >= next_nibble) { | 478 if (context->cycle >= next_nibble) { |
467 if (context->current_status_nibble == sizeof(cdd_status)) { | 479 if (context->current_status_nibble == sizeof(cdd_status)) { |
506 context->last_nibble_cycle = context->cycle; | 518 context->last_nibble_cycle = context->cycle; |
507 next_cmd_nibble = context->cycle + NIBBLE_CLOCKS; | 519 next_cmd_nibble = context->cycle + NIBBLE_CLOCKS; |
508 } | 520 } |
509 } | 521 } |
510 if (context->cycle >= next_byte) { | 522 if (context->cycle >= next_byte) { |
511 uint8_t byte = context->media->read(context->media, context->current_sector_byte); | 523 if (context->current_sector_byte >= 0) { |
512 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte); | 524 uint8_t byte = context->media->read(context->media, context->current_sector_byte); |
525 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte); | |
526 cdd_fader_data(fader, gate_array[GAO_CDD_CTRL] & BIT_MUTE ? 0 : byte); | |
527 } else { | |
528 cdd_fader_data(fader, 0); | |
529 } | |
513 context->last_byte_cycle = context->cycle; | 530 context->last_byte_cycle = context->cycle; |
514 if (context->current_sector_byte == 2352) { | 531 if (context->current_sector_byte == 2352) { |
515 context->current_sector_byte = -1; | 532 context->current_sector_byte = -1; |
516 next_byte = CYCLE_NEVER; | 533 } |
517 } else { | 534 next_byte = context->cycle + BYTE_CLOCKS; |
518 next_byte = context->cycle + BYTE_CLOCKS; | |
519 } | |
520 } | 535 } |
521 } | 536 } |
522 } | 537 } |
523 | 538 |
524 void cdd_mcu_start_cmd_recv(cdd_mcu *context, uint16_t *gate_array) | 539 void cdd_mcu_start_cmd_recv(cdd_mcu *context, uint16_t *gate_array) |
542 void cdd_hock_disabled(cdd_mcu *context) | 557 void cdd_hock_disabled(cdd_mcu *context) |
543 { | 558 { |
544 context->last_subcode_cycle = CYCLE_NEVER; | 559 context->last_subcode_cycle = CYCLE_NEVER; |
545 context->next_int_cycle = CYCLE_NEVER; | 560 context->next_int_cycle = CYCLE_NEVER; |
546 context->last_nibble_cycle = CYCLE_NEVER; | 561 context->last_nibble_cycle = CYCLE_NEVER; |
547 context->last_byte_cycle = CYCLE_NEVER; | |
548 context->current_status_nibble = -1; | 562 context->current_status_nibble = -1; |
549 context->current_cmd_nibble = -1; | 563 context->current_cmd_nibble = -1; |
550 } | 564 } |
551 | 565 |
552 void cdd_mcu_adjust_cycle(cdd_mcu *context, uint32_t deduction) | 566 void cdd_mcu_adjust_cycle(cdd_mcu *context, uint32_t deduction) |