Mercurial > repos > blastem
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; |