comparison cdd_mcu.c @ 2419:0871f555eff6

Fix some CD-ROM emulation issues and make timing better match my MCD2. Seems to fix or at least improve video playback in Iron Helix and Power Rangers
author Michael Pavone <pavone@retrodev.com>
date Thu, 18 Jan 2024 23:03:58 -0800
parents c66e051de8a6
children bcfa5e272f5e
comparison
equal deleted inserted replaced
2418:cc07f544c620 2419:0871f555eff6
9 #define SECTORS_PER_SECOND 75 9 #define SECTORS_PER_SECOND 75
10 #define SECTOR_CLOCKS (CD_BLOCK_CLKS/SECTORS_PER_SECOND) 10 #define SECTOR_CLOCKS (CD_BLOCK_CLKS/SECTORS_PER_SECOND)
11 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77) 11 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77)
12 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96 12 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96
13 #define SUBCODE_CLOCKS (SECTOR_CLOCKS/98) 13 #define SUBCODE_CLOCKS (SECTOR_CLOCKS/98)
14 #define PROCESSING_DELAY 54000 //approximate, based on Wondermega M1 measurements 14 #define PROCESSING_DELAY 121600 //approximate, based on relative level 4 and level 5 interrupt timing on MCD2 in pause_test
15 15
16 //lead in start max diameter 46 mm 16 //lead in start max diameter 46 mm
17 //program area start max diameter 50 mm 17 //program area start max diameter 50 mm
18 //difference 4 mm = 4000 um 18 //difference 4 mm = 4000 um
19 //radius difference 2 mm = 2000 um 19 //radius difference 2 mm = 2000 um
177 } 177 }
178 178
179 static void update_status(cdd_mcu *context, uint16_t *gate_array) 179 static void update_status(cdd_mcu *context, uint16_t *gate_array)
180 { 180 {
181 gate_array[GAO_CDD_CTRL] |= BIT_MUTE; 181 gate_array[GAO_CDD_CTRL] |= BIT_MUTE;
182 uint32_t prev_pba = context->head_pba;
183 switch (context->status) 182 switch (context->status)
184 { 183 {
185 case DS_STOP: 184 case DS_STOP:
186 handle_seek(context); 185 handle_seek(context);
187 break; 186 break;
253 } 252 }
254 if (context->first_cmd_received) { 253 if (context->first_cmd_received) {
255 switch (force_not_ready ? SF_NOTREADY : context->requested_format) 254 switch (force_not_ready ? SF_NOTREADY : context->requested_format)
256 { 255 {
257 case SF_ABSOLUTE: 256 case SF_ABSOLUTE:
258 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) { 257 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
259 lba_to_status(context, prev_pba - LEADIN_SECTORS); 258 lba_to_status(context, context->head_pba - LEADIN_SECTORS);
260 context->status_buffer.format = SF_ABSOLUTE; 259 context->status_buffer.format = SF_ABSOLUTE;
261 } else { 260 } else {
262 context->status_buffer.format = SF_NOTREADY; 261 context->status_buffer.format = SF_NOTREADY;
263 } 262 }
264 break; 263 break;
265 case SF_RELATIVE: 264 case SF_RELATIVE:
266 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) { 265 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
267 uint32_t lba =prev_pba - LEADIN_SECTORS; 266 uint32_t lba =context->head_pba - LEADIN_SECTORS;
268 for (uint32_t i = 0; i < context->media->num_tracks; i++) 267 for (uint32_t i = 0; i < context->media->num_tracks; i++)
269 { 268 {
270 if (lba < context->media->tracks[i].end_lba) { 269 if (lba < context->media->tracks[i].end_lba) {
271 if (context->media->tracks[i].fake_pregap) { 270 if (context->media->tracks[i].fake_pregap) {
272 if (lba > context->media->tracks[i].fake_pregap) { 271 if (lba > context->media->tracks[i].fake_pregap) {
293 } else { 292 } else {
294 context->status_buffer.format = SF_NOTREADY; 293 context->status_buffer.format = SF_NOTREADY;
295 } 294 }
296 break; 295 break;
297 case SF_TRACK: 296 case SF_TRACK:
298 if (context->toc_valid && prev_pba >= LEADIN_SECTORS) { 297 if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
299 uint32_t lba =prev_pba - LEADIN_SECTORS; 298 uint32_t lba =context->head_pba - LEADIN_SECTORS;
300 uint32_t i; 299 uint32_t i;
301 for (i = 0; i < context->media->num_tracks; i++) 300 for (i = 0; i < context->media->num_tracks; i++)
302 { 301 {
303 if (lba < context->media->tracks[i].end_lba) { 302 if (lba < context->media->tracks[i].end_lba) {
304 if (context->media->tracks[i].fake_pregap) { 303 if (context->media->tracks[i].fake_pregap) {
371 for (uint32_t i = 0; i < context->requested_track; i++) { 370 for (uint32_t i = 0; i < context->requested_track; i++) {
372 lba += context->media->tracks[i].fake_pregap; 371 lba += context->media->tracks[i].fake_pregap;
373 } 372 }
374 lba_to_status(context, lba); 373 lba_to_status(context, lba);
375 if (context->media->tracks[context->requested_track - 1].type == TRACK_DATA) { 374 if (context->media->tracks[context->requested_track - 1].type == TRACK_DATA) {
376 context->status_buffer.b.tocn.frame_low |= 0x80; 375 context->status_buffer.b.tocn.frame_high |= 0x8;
377 } 376 }
378 context->status_buffer.b.tocn.track_low = context->requested_track % 10; 377 context->status_buffer.b.tocn.track_low = context->requested_track % 10;
379 context->status_buffer.format = SF_TOCN; 378 context->status_buffer.format = SF_TOCN;
380 } else { 379 } else {
381 context->status_buffer.format = SF_NOTREADY; 380 context->status_buffer.format = SF_NOTREADY;
661 context->next_subcode_int_cycle = cd_block_to_mclks(next_subcode); 660 context->next_subcode_int_cycle = cd_block_to_mclks(next_subcode);
662 } else { 661 } else {
663 context->next_subcode_int_cycle = CYCLE_NEVER; 662 context->next_subcode_int_cycle = CYCLE_NEVER;
664 } 663 }
665 if (old_coarse != context->coarse_seek) { 664 if (old_coarse != context->coarse_seek) {
666 context->next_int_cycle = cd_block_to_mclks(context->cycle + PROCESSING_DELAY + 7 * NIBBLE_CLOCKS); 665 context->next_int_cycle = cd_block_to_mclks(next_nibble + 7 * NIBBLE_CLOCKS);
667 if (context->coarse_seek % 3) {
668 context->next_int_cycle += cd_block_to_mclks(SECTOR_CLOCKS * (3 - (context->coarse_seek % 3)));
669 }
670 } 666 }
671 } 667 }
672 if (context->cycle >= next_nibble) { 668 if (context->cycle >= next_nibble) {
673 if (context->current_status_nibble == sizeof(cdd_status)) { 669 if (context->current_status_nibble == sizeof(cdd_status)) {
674 context->current_status_nibble = -1; 670 context->current_status_nibble = -1;
719 context->last_nibble_cycle = context->cycle; 715 context->last_nibble_cycle = context->cycle;
720 next_cmd_nibble = context->cycle + NIBBLE_CLOCKS; 716 next_cmd_nibble = context->cycle + NIBBLE_CLOCKS;
721 } 717 }
722 } 718 }
723 if (context->cycle >= context->next_byte_cycle) { 719 if (context->cycle >= context->next_byte_cycle) {
724 if (context->current_sector_byte >= 0 && (!fader->byte_counter || context->current_sector_byte)) { 720 if (context->current_sector_byte >= 0/* && (!fader->byte_counter || context->current_sector_byte)*/) {
721 if (!context->current_sector_byte) {
722 //HACK: things can get a little out of sync currently which causes a mess in the fader code
723 // since it expects even multiples of 4 bytes (1 stereo sample)
724 while (fader->byte_counter)
725 {
726 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
727 cdd_fader_data(fader, 0);
728 }
729 }
725 uint8_t byte = context->media->read(context->media, context->current_sector_byte); 730 uint8_t byte = context->media->read(context->media, context->current_sector_byte);
726 if (context->status != DS_PLAY) { 731 if (context->status != DS_PLAY) {
727 byte = 0; 732 byte = 0;
728 } 733 }
729 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte); 734 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), context->current_sector_byte++, byte);
730 cdd_fader_data(fader, gate_array[GAO_CDD_CTRL] & BIT_MUTE ? 0 : byte); 735 cdd_fader_data(fader, gate_array[GAO_CDD_CTRL] & BIT_MUTE ? 0 : byte);
731 } else { 736 } else {
732 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0); 737 lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
733 cdd_fader_data(fader, 0); 738 cdd_fader_data(fader, 0);
734 if (context->current_sector_byte >= 0) {
735 next_subcode += BYTE_CLOCKS;
736 context->last_sector_cycle += BYTE_CLOCKS;
737 }
738 } 739 }
739 if (context->current_sector_byte == 2352) { 740 if (context->current_sector_byte == 2352) {
740 context->current_sector_byte = -1; 741 context->current_sector_byte = -1;
741 } 742 }
742 context->next_byte_cycle += BYTE_CLOCKS; 743 context->next_byte_cycle += BYTE_CLOCKS;