Mercurial > repos > blastem
comparison segacd.c @ 2061:7c1760b5b3e5 segacd
Implemented basic TOC functionality of CDD MCU
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 27 Jan 2022 00:33:41 -0800 |
parents | 70260f6051dd |
children | 07ed42bd7b4c |
comparison
equal
deleted
inserted
replaced
2060:f1c2415f4d1d | 2061:7c1760b5b3e5 |
---|---|
79 #define BIT_MASK_IEN3 0x0008 | 79 #define BIT_MASK_IEN3 0x0008 |
80 #define BIT_MASK_IEN4 0x0010 | 80 #define BIT_MASK_IEN4 0x0010 |
81 #define BIT_MASK_IEN5 0x0020 | 81 #define BIT_MASK_IEN5 0x0020 |
82 #define BIT_MASK_IEN6 0x0040 | 82 #define BIT_MASK_IEN6 0x0040 |
83 | 83 |
84 //GA_CDD_CTRL | |
85 #define BIT_HOCK 0x0004 | |
86 | |
84 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value) | 87 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value) |
85 { | 88 { |
86 m68k_context *m68k = vcontext; | 89 m68k_context *m68k = vcontext; |
87 segacd_context *cd = m68k->system; | 90 segacd_context *cd = m68k->system; |
88 //if (!(cd->gate_array[GA_MEM_MODE] & (1 << ((address >> 9) + 8)))) { | 91 //if (!(cd->gate_array[GA_MEM_MODE] & (1 << ((address >> 9) + 8)))) { |
306 static void calculate_target_cycle(m68k_context * context) | 309 static void calculate_target_cycle(m68k_context * context) |
307 { | 310 { |
308 segacd_context *cd = context->system; | 311 segacd_context *cd = context->system; |
309 context->int_cycle = CYCLE_NEVER; | 312 context->int_cycle = CYCLE_NEVER; |
310 uint8_t mask = context->status & 0x7; | 313 uint8_t mask = context->status & 0x7; |
311 if (mask < 3) { | 314 if (mask < 4) { |
312 uint32_t next_timer; | 315 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) { |
313 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { | 316 uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle; |
314 uint32_t next_timer_cycle = next_timer_int(cd); | 317 if (cdd_cycle < context->int_cycle) { |
315 if (next_timer_cycle < context->int_cycle) { | 318 context->int_cycle = cdd_cycle; |
316 context->int_cycle = next_timer_cycle; | 319 context->int_num = 4; |
317 context->int_num = 3; | 320 } |
318 } | 321 } |
319 } | 322 if (mask < 3) { |
320 if (mask < 2) { | 323 uint32_t next_timer; |
321 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | 324 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { |
322 context->int_cycle = cd->int2_cycle; | 325 uint32_t next_timer_cycle = next_timer_int(cd); |
323 context->int_num = 2; | 326 if (next_timer_cycle < context->int_cycle) { |
327 context->int_cycle = next_timer_cycle; | |
328 context->int_num = 3; | |
329 } | |
330 } | |
331 if (mask < 2) { | |
332 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | |
333 context->int_cycle = cd->int2_cycle; | |
334 context->int_num = 2; | |
335 } | |
324 } | 336 } |
325 } | 337 } |
326 } | 338 } |
327 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { | 339 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { |
328 context->int_pending = INT_PENDING_NONE; | 340 context->int_pending = INT_PENDING_NONE; |
361 return lc8951_reg_read(&cd->cdc); | 373 return lc8951_reg_read(&cd->cdc); |
362 case GA_STOP_WATCH: | 374 case GA_STOP_WATCH: |
363 case GA_TIMER: | 375 case GA_TIMER: |
364 timers_run(cd, m68k->current_cycle); | 376 timers_run(cd, m68k->current_cycle); |
365 return cd->gate_array[reg]; | 377 return cd->gate_array[reg]; |
378 case GA_CDD_STATUS0: | |
379 case GA_CDD_STATUS1: | |
380 case GA_CDD_STATUS2: | |
381 case GA_CDD_STATUS3: | |
382 case GA_CDD_STATUS4: | |
383 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | |
384 return cd->gate_array[reg]; | |
385 break; | |
366 case GA_FONT_DATA0: | 386 case GA_FONT_DATA0: |
367 case GA_FONT_DATA1: | 387 case GA_FONT_DATA1: |
368 case GA_FONT_DATA2: | 388 case GA_FONT_DATA2: |
369 case GA_FONT_DATA3: { | 389 case GA_FONT_DATA3: { |
370 uint16_t shift = 4 * (3 - (reg - GA_FONT_DATA0)); | 390 uint16_t shift = 4 * (3 - (reg - GA_FONT_DATA0)); |
497 break; | 517 break; |
498 case GA_INT_MASK: | 518 case GA_INT_MASK: |
499 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); | 519 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); |
500 calculate_target_cycle(m68k); | 520 calculate_target_cycle(m68k); |
501 break; | 521 break; |
522 case GA_CDD_CTRL: { | |
523 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | |
524 uint16_t changed = cd->gate_array[reg] ^ value; | |
525 cd->gate_array[reg] &= ~BIT_HOCK; | |
526 cd->gate_array[reg] |= value & BIT_HOCK; | |
527 if (changed & BIT_HOCK) { | |
528 if (value & BIT_HOCK) { | |
529 cdd_hock_enabled(&cd->cdd); | |
530 } else { | |
531 cdd_hock_disabled(&cd->cdd); | |
532 } | |
533 calculate_target_cycle(m68k); | |
534 } | |
535 break; | |
536 } | |
537 case GA_CDD_CMD0: | |
538 case GA_CDD_CMD1: | |
539 case GA_CDD_CMD2: | |
540 case GA_CDD_CMD3: | |
541 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | |
542 cd->gate_array[reg] = value & 0x0F0F; | |
543 break; | |
544 case GA_CDD_CMD4: | |
545 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | |
546 cd->gate_array[reg] = value & 0x0F0F; | |
547 cdd_mcu_start_cmd_recv(&cd->cdd, cd->gate_array + GA_CDD_CTRL); | |
548 break; | |
502 case GA_FONT_COLOR: | 549 case GA_FONT_COLOR: |
503 cd->gate_array[reg] = value & 0xFF; | 550 cd->gate_array[reg] = value & 0xFF; |
504 break; | 551 break; |
505 case GA_FONT_BITS: | 552 case GA_FONT_BITS: |
506 cd->gate_array[reg] = value; | 553 cd->gate_array[reg] = value; |
534 lc8951_ar_write(&cd->cdc, value); | 581 lc8951_ar_write(&cd->cdc, value); |
535 } else { | 582 } else { |
536 cd->gate_array[reg] = value << 8; | 583 cd->gate_array[reg] = value << 8; |
537 } | 584 } |
538 return vcontext; | 585 return vcontext; |
586 case GA_CDD_CMD4: | |
587 if (!address) { | |
588 //byte write to $FF804A should not trigger transfer | |
589 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | |
590 cd->gate_array[reg] &= 0x0F; | |
591 cd->gate_array[reg] |= (value << 8 & 0x0F00); | |
592 return vcontext; | |
593 } | |
594 //intentional fallthrough for $FF804B | |
539 default: | 595 default: |
540 if (address & 1) { | 596 if (address & 1) { |
541 value16 = cd->gate_array[reg] & 0xFF00 | value; | 597 value16 = cd->gate_array[reg] & 0xFF00 | value; |
542 } else { | 598 } else { |
543 value16 = cd->gate_array[reg] & 0xFF | (value << 8); | 599 value16 = cd->gate_array[reg] & 0xFF | (value << 8); |
553 } | 609 } |
554 | 610 |
555 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle) | 611 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle) |
556 { | 612 { |
557 timers_run(cd, cycle); | 613 timers_run(cd, cycle); |
614 cdd_mcu_run(&cd->cdd, cycle, cd->gate_array + GA_CDD_CTRL); | |
558 } | 615 } |
559 | 616 |
560 static m68k_context *sync_components(m68k_context * context, uint32_t address) | 617 static m68k_context *sync_components(m68k_context * context, uint32_t address) |
561 { | 618 { |
562 segacd_context *cd = context->system; | 619 segacd_context *cd = context->system; |
567 cd->int2_cycle = CYCLE_NEVER; | 624 cd->int2_cycle = CYCLE_NEVER; |
568 break; | 625 break; |
569 case 3: | 626 case 3: |
570 cd->timer_pending = 0; | 627 cd->timer_pending = 0; |
571 break; | 628 break; |
629 case 4: | |
630 cd->cdd.int_pending = 0; | |
572 } | 631 } |
573 context->int_ack = 0; | 632 context->int_ack = 0; |
574 calculate_target_cycle(context); | 633 calculate_target_cycle(context); |
575 return context; | 634 return context; |
576 } | 635 } |
611 if (deduction >= cd->periph_reset_cycle) { | 670 if (deduction >= cd->periph_reset_cycle) { |
612 cd->periph_reset_cycle = CYCLE_NEVER; | 671 cd->periph_reset_cycle = CYCLE_NEVER; |
613 } else if (cd->periph_reset_cycle != CYCLE_NEVER) { | 672 } else if (cd->periph_reset_cycle != CYCLE_NEVER) { |
614 cd->periph_reset_cycle -= deduction; | 673 cd->periph_reset_cycle -= deduction; |
615 } | 674 } |
675 cdd_mcu_adjust_cycle(&cd->cdd, deduction); | |
616 } | 676 } |
617 | 677 |
618 static uint16_t main_gate_read16(uint32_t address, void *vcontext) | 678 static uint16_t main_gate_read16(uint32_t address, void *vcontext) |
619 { | 679 { |
620 m68k_context *m68k = vcontext; | 680 m68k_context *m68k = vcontext; |
847 cd->reset = 1; //active low, so reset is not active on start | 907 cd->reset = 1; //active low, so reset is not active on start |
848 cd->memptr_start_index = 0; | 908 cd->memptr_start_index = 0; |
849 cd->gate_array[1] = 1; | 909 cd->gate_array[1] = 1; |
850 cd->gate_array[0x1B] = 0x100; | 910 cd->gate_array[0x1B] = 0x100; |
851 lc8951_init(&cd->cdc); | 911 lc8951_init(&cd->cdc); |
912 if (media->chain && media->type != MEDIA_CDROM) { | |
913 media = media->chain; | |
914 } | |
915 cdd_mcu_init(&cd->cdd, media); | |
852 | 916 |
853 return cd; | 917 return cd; |
854 } | 918 } |
855 | 919 |
856 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint8_t cart_boot, uint32_t *num_chunks) | 920 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint8_t cart_boot, uint32_t *num_chunks) |