Mercurial > repos > blastem
comparison segacd.c @ 2116:cd057d6fe030
Initial stab at subcode emulation
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 06 Mar 2022 22:03:52 -0800 |
parents | 4be496489eda |
children | 5ec2f97365a2 |
comparison
equal
deleted
inserted
replaced
2115:e93ced356a21 | 2116:cd057d6fe030 |
---|---|
53 GA_FONT_BITS, | 53 GA_FONT_BITS, |
54 GA_FONT_DATA0, | 54 GA_FONT_DATA0, |
55 GA_FONT_DATA1, | 55 GA_FONT_DATA1, |
56 GA_FONT_DATA2, | 56 GA_FONT_DATA2, |
57 GA_FONT_DATA3, | 57 GA_FONT_DATA3, |
58 GA_SUBCODE_START = 0x80, | |
59 GA_SUBCODE_MIRROR = 0xC0, | |
58 | 60 |
59 GA_HINT_VECTOR = GA_CDC_REG_DATA | 61 GA_HINT_VECTOR = GA_CDC_REG_DATA |
60 }; | 62 }; |
61 //GA_SUB_CPU_CTRL | 63 //GA_SUB_CPU_CTRL |
62 #define BIT_IEN2 0x8000 | 64 #define BIT_IEN2 0x8000 |
385 { | 387 { |
386 segacd_context *cd = context->system; | 388 segacd_context *cd = context->system; |
387 context->int_cycle = CYCLE_NEVER; | 389 context->int_cycle = CYCLE_NEVER; |
388 uint8_t mask = context->status & 0x7; | 390 uint8_t mask = context->status & 0x7; |
389 uint32_t cdc_cycle = CYCLE_NEVER; | 391 uint32_t cdc_cycle = CYCLE_NEVER; |
390 if (mask < 5) { | 392 if (mask < 6) { |
391 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) { | 393 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN6) { |
392 cdc_cycle = lc8951_next_interrupt(&cd->cdc); | 394 uint32_t subcode_cycle = cd->cdd.subcode_int_pending ? context->current_cycle : cd->cdd.next_subcode_int_cycle; |
393 //CDC interrupts only generated on falling edge of !INT signal | 395 if (subcode_cycle != CYCLE_NEVER) { |
394 if (cd->cdc_int_ack) { | 396 context->int_cycle = subcode_cycle; |
395 if (cdc_cycle > cd->cdc.cycle) { | 397 context->int_num = 6; |
396 cd->cdc_int_ack = 0; | 398 } |
397 } else { | 399 } |
398 cdc_cycle = CYCLE_NEVER; | 400 if (mask < 5) { |
399 } | 401 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) { |
400 } | 402 cdc_cycle = lc8951_next_interrupt(&cd->cdc); |
401 if (cdc_cycle < context->int_cycle) { | 403 //CDC interrupts only generated on falling edge of !INT signal |
402 context->int_cycle = cdc_cycle; | 404 if (cd->cdc_int_ack) { |
403 context->int_num = 5; | 405 if (cdc_cycle > cd->cdc.cycle) { |
404 } | 406 cd->cdc_int_ack = 0; |
405 } | 407 } else { |
406 if (mask < 4) { | 408 cdc_cycle = CYCLE_NEVER; |
407 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) { | |
408 uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle; | |
409 if (cdd_cycle < context->int_cycle) { | |
410 context->int_cycle = cdd_cycle; | |
411 context->int_num = 4; | |
412 } | |
413 } | |
414 if (mask < 3) { | |
415 uint32_t next_timer; | |
416 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { | |
417 uint32_t next_timer_cycle = next_timer_int(cd); | |
418 if (next_timer_cycle < context->int_cycle) { | |
419 context->int_cycle = next_timer_cycle; | |
420 context->int_num = 3; | |
421 } | 409 } |
422 } | 410 } |
423 if (mask < 2) { | 411 if (cdc_cycle < context->int_cycle) { |
424 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | 412 context->int_cycle = cdc_cycle; |
425 context->int_cycle = cd->int2_cycle; | 413 context->int_num = 5; |
426 context->int_num = 2; | 414 } |
415 } | |
416 if (mask < 4) { | |
417 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) { | |
418 uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle; | |
419 if (cdd_cycle < context->int_cycle) { | |
420 context->int_cycle = cdd_cycle; | |
421 context->int_num = 4; | |
427 } | 422 } |
428 if (mask < 1) { | 423 } |
429 if (cd->graphics_int_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN1)) { | 424 if (mask < 3) { |
430 context->int_cycle = cd->graphics_int_cycle; | 425 uint32_t next_timer; |
431 context->int_num = 1; | 426 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { |
427 uint32_t next_timer_cycle = next_timer_int(cd); | |
428 if (next_timer_cycle < context->int_cycle) { | |
429 context->int_cycle = next_timer_cycle; | |
430 context->int_num = 3; | |
431 } | |
432 } | |
433 if (mask < 2) { | |
434 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | |
435 context->int_cycle = cd->int2_cycle; | |
436 context->int_num = 2; | |
437 } | |
438 if (mask < 1) { | |
439 if (cd->graphics_int_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN1)) { | |
440 context->int_cycle = cd->graphics_int_cycle; | |
441 context->int_num = 1; | |
442 } | |
432 } | 443 } |
433 } | 444 } |
434 } | 445 } |
435 } | 446 } |
436 } | 447 } |
519 pixel = bg; | 530 pixel = bg; |
520 } | 531 } |
521 value |= pixel << (i * 4); | 532 value |= pixel << (i * 4); |
522 } | 533 } |
523 return value; | 534 return value; |
535 } | |
524 case GA_STAMP_SIZE: | 536 case GA_STAMP_SIZE: |
525 case GA_IMAGE_BUFFER_LINES: | 537 case GA_IMAGE_BUFFER_LINES: |
526 //these two have bits that change based on graphics operations | 538 //these two have bits that change based on graphics operations |
527 cd_graphics_run(cd, m68k->current_cycle); | 539 cd_graphics_run(cd, m68k->current_cycle); |
528 return cd->gate_array[reg]; | 540 return cd->gate_array[reg]; |
529 case GA_TRACE_VECTOR_BASE: | 541 case GA_TRACE_VECTOR_BASE: |
530 //write only | 542 //write only |
531 return 0xFFFF; | 543 return 0xFFFF; |
532 } | |
533 default: | 544 default: |
545 if (reg >= GA_SUBCODE_MIRROR) { | |
546 return cd->gate_array[GA_SUBCODE_START + (reg & 0x3F)]; | |
547 } | |
534 return cd->gate_array[reg]; | 548 return cd->gate_array[reg]; |
535 } | 549 } |
536 } | 550 } |
537 | 551 |
538 static uint8_t sub_gate_read8(uint32_t address, void *vcontext) | 552 static uint8_t sub_gate_read8(uint32_t address, void *vcontext) |
653 timers_run(cd, m68k->current_cycle); | 667 timers_run(cd, m68k->current_cycle); |
654 cd->gate_array[reg] = value & 0xFF; | 668 cd->gate_array[reg] = value & 0xFF; |
655 calculate_target_cycle(m68k); | 669 calculate_target_cycle(m68k); |
656 break; | 670 break; |
657 case GA_INT_MASK: | 671 case GA_INT_MASK: |
672 if (!(cd->gate_array[reg] & BIT_MASK_IEN6)) { | |
673 //subcode interrupts can't be made pending when they are disabled in this reg | |
674 cd->cdd.subcode_int_pending = 0; | |
675 } | |
658 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); | 676 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); |
659 calculate_target_cycle(m68k); | 677 calculate_target_cycle(m68k); |
660 break; | 678 break; |
661 case GA_CDD_FADER: | 679 case GA_CDD_FADER: |
662 cdd_run(cd, m68k->current_cycle); | 680 cdd_run(cd, m68k->current_cycle); |
900 case 4: | 918 case 4: |
901 cd->cdd.int_pending = 0; | 919 cd->cdd.int_pending = 0; |
902 break; | 920 break; |
903 case 5: | 921 case 5: |
904 cd->cdc_int_ack = 1; | 922 cd->cdc_int_ack = 1; |
923 break; | |
924 case 6: | |
925 cd->cdd.subcode_int_pending = 0; | |
905 break; | 926 break; |
906 } | 927 } |
907 context->int_ack = 0; | 928 context->int_ack = 0; |
908 calculate_target_cycle(context); | 929 calculate_target_cycle(context); |
909 return context; | 930 return context; |