Mercurial > repos > blastem
comparison genesis.c @ 2460:a4f8fa24764b
Initial work on emulating the YMZ263B in the Copera
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 23 Feb 2024 01:16:38 -0800 |
parents | cb62730d5c99 |
children | b5640ac9aea9 |
comparison
equal
deleted
inserted
replaced
2459:cb62730d5c99 | 2460:a4f8fa24764b |
---|---|
686 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) | 686 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) |
687 { | 687 { |
688 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES; | 688 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES; |
689 psg_run(gen->psg, cur_target); | 689 psg_run(gen->psg, cur_target); |
690 pico_pcm_run(gen->adpcm, cur_target); | 690 pico_pcm_run(gen->adpcm, cur_target); |
691 if (gen->ymz) { | |
692 ymz263b_run(gen->ymz, cur_target); | |
693 } | |
691 } | 694 } |
692 psg_run(gen->psg, target); | 695 psg_run(gen->psg, target); |
693 pico_pcm_run(gen->adpcm, target); | 696 pico_pcm_run(gen->adpcm, target); |
697 if (gen->ymz) { | |
698 ymz263b_run(gen->ymz, target); | |
699 } | |
694 } | 700 } |
695 | 701 |
696 static void adjust_int_cycle_pico(m68k_context *context, vdp_context *v_context) | 702 static void adjust_int_cycle_pico(m68k_context *context, vdp_context *v_context) |
697 { | 703 { |
698 genesis_context *gen = context->system; | 704 genesis_context *gen = context->system; |
715 context->int_cycle = next_hint; | 721 context->int_cycle = next_hint; |
716 context->int_num = 5; | 722 context->int_num = 5; |
717 | 723 |
718 } | 724 } |
719 } | 725 } |
720 if (mask < 3) { | 726 if (mask < 4) { |
721 uint32_t next_pcm_int = pico_pcm_next_int(gen->adpcm); | 727 if (v_context->regs[REG_MODE_3] & BIT_EINT_EN) { |
722 if (next_pcm_int != CYCLE_NEVER && next_pcm_int < context->int_cycle) { | |
723 context->int_cycle = next_pcm_int; | |
724 context->int_num = 3; | |
725 } | |
726 if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN) && gen->header.type == SYSTEM_GENESIS) { | |
727 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); | 728 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); |
728 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); | 729 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); |
729 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); | 730 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); |
730 uint32_t next_eint = next_eint_port0 < next_eint_port1 | 731 uint32_t next_eint = next_eint_port0 < next_eint_port1 |
731 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) | 732 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) |
736 context->int_cycle = next_eint; | 737 context->int_cycle = next_eint; |
737 context->int_num = 2; | 738 context->int_num = 2; |
738 } | 739 } |
739 } | 740 } |
740 } | 741 } |
742 if (mask < 3) { | |
743 uint32_t next_pcm_int = pico_pcm_next_int(gen->adpcm); | |
744 if (next_pcm_int != CYCLE_NEVER && next_pcm_int < context->int_cycle) { | |
745 context->int_cycle = next_pcm_int; | |
746 context->int_num = 3; | |
747 } | |
748 | |
749 if (mask < 2 && gen->ymz) { | |
750 uint32_t ymz_int = ymz263b_next_int(gen->ymz); | |
751 if (ymz_int < context->int_cycle) { | |
752 context->int_cycle = ymz_int; | |
753 context->int_num = 2; | |
754 } | |
755 } | |
756 } | |
741 } | 757 } |
742 } | 758 } |
743 } | 759 } |
744 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { | 760 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { |
745 context->int_pending = INT_PENDING_NONE; | 761 context->int_pending = INT_PENDING_NONE; |
832 if (gen->psg->vgm) { | 848 if (gen->psg->vgm) { |
833 vgm_adjust_cycles(gen->psg->vgm, deduction); | 849 vgm_adjust_cycles(gen->psg->vgm, deduction); |
834 } | 850 } |
835 gen->psg->cycles -= deduction; | 851 gen->psg->cycles -= deduction; |
836 gen->adpcm->cycle -= deduction; | 852 gen->adpcm->cycle -= deduction; |
853 if (gen->ymz) { | |
854 gen->ymz->cycle -= deduction; | |
855 } | |
837 if (gen->reset_cycle != CYCLE_NEVER) { | 856 if (gen->reset_cycle != CYCLE_NEVER) { |
838 gen->reset_cycle -= deduction; | 857 gen->reset_cycle -= deduction; |
839 } | 858 } |
840 event_cycle_adjust(mclks, deduction); | 859 event_cycle_adjust(mclks, deduction); |
841 if (gen->expansion) { | 860 if (gen->expansion) { |
904 } | 923 } |
905 | 924 |
906 static m68k_context *int_ack(m68k_context *context) | 925 static m68k_context *int_ack(m68k_context *context) |
907 { | 926 { |
908 genesis_context * gen = context->system; | 927 genesis_context * gen = context->system; |
909 if ((gen->header.type != SYSTEM_PICO && gen->header.type != SYSTEM_COPERA) || context->int_num > 4 || context->int_num < 3) { | 928 if ((gen->header.type != SYSTEM_PICO && gen->header.type != SYSTEM_COPERA) || context->int_num > 3) { |
910 vdp_context * v_context = gen->vdp; | 929 vdp_context * v_context = gen->vdp; |
911 //printf("acknowledging %d @ %d:%d, vcounter: %d, hslot: %d\n", context->int_ack, context->current_cycle, v_context->cycles, v_context->vcounter, v_context->hslot); | 930 //printf("acknowledging %d @ %d:%d, vcounter: %d, hslot: %d\n", context->int_ack, context->current_cycle, v_context->cycles, v_context->vcounter, v_context->hslot); |
912 vdp_run_context(v_context, context->current_cycle); | 931 vdp_run_context(v_context, context->current_cycle); |
913 vdp_int_ack(v_context); | 932 vdp_int_ack(v_context); |
914 } | 933 } |
1559 return 0xFFFF; | 1578 return 0xFFFF; |
1560 } | 1579 } |
1561 | 1580 |
1562 static uint8_t copera_io_read(uint32_t location, void *vcontext) | 1581 static uint8_t copera_io_read(uint32_t location, void *vcontext) |
1563 { | 1582 { |
1564 printf("Unhandled Copera 8-bit read %X\n", location); | 1583 uint8_t ret; |
1565 return 0xFF; | 1584 m68k_context *m68k = vcontext; |
1566 } | 1585 genesis_context *gen = m68k->system; |
1567 | |
1568 static void* copera_io_write_w(uint32_t location, void *vcontext, uint16_t value) | |
1569 { | |
1570 printf("Unhandled Copera 16-bit write %X: %X\n", location, value); | |
1571 return vcontext; | |
1572 } | |
1573 | |
1574 static void* copera_io_write(uint32_t location, void *vcontext, uint8_t value) | |
1575 { | |
1576 switch (location & 0xFF) | 1586 switch (location & 0xFF) |
1577 { | 1587 { |
1578 case 1: | 1588 case 1: |
1579 case 5: | 1589 case 5: |
1590 ymz263b_run(gen->ymz, m68k->current_cycle); | |
1591 ret = ymz263b_status_read(gen->ymz); | |
1592 printf("Copera YMZ263 Status read - %X: %X\n", location, ret); | |
1593 adjust_int_cycle_pico(gen->m68k, gen->vdp); | |
1594 return ret; | |
1595 case 3: | |
1596 case 7: | |
1597 ymz263b_run(gen->ymz, m68k->current_cycle); | |
1598 ret = ymz263b_data_read(gen->ymz, location & 4); | |
1599 printf("Copera YMZ263 Data read - %X: %X\n", location, ret); | |
1600 return ret; | |
1601 default: | |
1602 printf("Unhandled Copera 8-bit read %X\n", location); | |
1603 return 0xFF; | |
1604 } | |
1605 } | |
1606 | |
1607 static void* copera_io_write_w(uint32_t location, void *vcontext, uint16_t value) | |
1608 { | |
1609 printf("Unhandled Copera 16-bit write %X: %X\n", location, value); | |
1610 return vcontext; | |
1611 } | |
1612 | |
1613 static void* copera_io_write(uint32_t location, void *vcontext, uint8_t value) | |
1614 { | |
1615 m68k_context *m68k = vcontext; | |
1616 genesis_context *gen = m68k->system; | |
1617 switch (location & 0xFF) | |
1618 { | |
1619 case 1: | |
1620 case 5: | |
1621 ymz263b_run(gen->ymz, m68k->current_cycle); | |
1580 printf("Copera YMZ263 Address write - %X: %X\n", location, value); | 1622 printf("Copera YMZ263 Address write - %X: %X\n", location, value); |
1623 ymz263b_address_write(gen->ymz, value); | |
1581 break; | 1624 break; |
1582 case 3: | 1625 case 3: |
1583 case 7: | 1626 case 7: |
1627 ymz263b_run(gen->ymz, m68k->current_cycle); | |
1584 printf("Copera YMZ263 Channel #%d Data write - %X: %X\n", ((location & 4) >> 2) + 1, location, value); | 1628 printf("Copera YMZ263 Channel #%d Data write - %X: %X\n", ((location & 4) >> 2) + 1, location, value); |
1629 ymz263b_data_write(gen->ymz, location & 4, value); | |
1630 adjust_int_cycle_pico(gen->m68k, gen->vdp); | |
1585 break; | 1631 break; |
1586 case 0x24: | 1632 case 0x24: |
1587 case 0x34: | 1633 case 0x34: |
1588 printf("Copera YMF263 Address Part #%d write - %X: %X\n", ((location >> 4) & 1) + 1, location, value); | 1634 printf("Copera YMF262 Address Part #%d write - %X: %X\n", ((location >> 4) & 1) + 1, location, value); |
1589 break; | 1635 break; |
1590 case 0x28: | 1636 case 0x28: |
1591 printf("Copera YMF263 Data write - %X: %X\n", location, value); | 1637 printf("Copera YMF262 Data write - %X: %X\n", location, value); |
1592 break; | 1638 break; |
1593 case 0x40: | 1639 case 0x40: |
1594 //Bit 4 = SCI | 1640 //Bit 4 = SCI |
1595 //Bit 5 = DIN | 1641 //Bit 5 = DIN |
1596 //Bit 6 = A0 | 1642 //Bit 6 = A0 |
2157 free(gen->zram); | 2203 free(gen->zram); |
2158 } | 2204 } |
2159 if (gen->header.type == SYSTEM_PICO || gen->header.type == SYSTEM_COPERA) { | 2205 if (gen->header.type == SYSTEM_PICO || gen->header.type == SYSTEM_COPERA) { |
2160 pico_pcm_free(gen->adpcm); | 2206 pico_pcm_free(gen->adpcm); |
2161 free(gen->adpcm); | 2207 free(gen->adpcm); |
2208 if (gen->ymz) { | |
2209 //TODO: call cleanup function once it exists | |
2210 free(gen->ymz); | |
2211 } | |
2162 } else { | 2212 } else { |
2163 ym_free(gen->ym); | 2213 ym_free(gen->ym); |
2164 } | 2214 } |
2165 psg_free(gen->psg); | 2215 psg_free(gen->psg); |
2166 free(gen->header.save_dir); | 2216 free(gen->header.save_dir); |
3123 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); | 3173 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); |
3124 | 3174 |
3125 gen->adpcm = calloc(1, sizeof(pico_pcm)); | 3175 gen->adpcm = calloc(1, sizeof(pico_pcm)); |
3126 pico_pcm_init(gen->adpcm, gen->master_clock, 42); | 3176 pico_pcm_init(gen->adpcm, gen->master_clock, 42); |
3127 | 3177 |
3178 if (stype == SYSTEM_COPERA) { | |
3179 gen->ymz = calloc(1, sizeof(*gen->ymz)); | |
3180 //This divider is just a guess, PCB diagram in MAME shows no other crystal | |
3181 //Datasheet says the typical clock is 16.9344 MHz | |
3182 //Master clock / 3 is 17.897725 MHz which is reasonably close | |
3183 ymz263b_init(gen->ymz, 3); | |
3184 } | |
3185 | |
3128 gen->work_ram = calloc(2, RAM_WORDS); | 3186 gen->work_ram = calloc(2, RAM_WORDS); |
3129 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) | 3187 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) |
3130 { | 3188 { |
3131 srand(time(NULL)); | 3189 srand(time(NULL)); |
3132 for (int i = 0; i < RAM_WORDS; i++) | 3190 for (int i = 0; i < RAM_WORDS; i++) |