comparison genesis.c @ 2431:61c0bfe10887

Somewhat busted support for Pico ADPCM
author Michael Pavone <pavone@retrodev.com>
date Tue, 06 Feb 2024 21:47:11 -0800
parents da3dc881d3f0
children 2907c3312423
comparison
equal deleted inserted replaced
2430:fb8d6ebf9d5f 2431:61c0bfe10887
679 } 679 }
680 } 680 }
681 return context; 681 return context;
682 } 682 }
683 683
684 static void sync_sound_pico(genesis_context * gen, uint32_t target)
685 {
686 while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES)
687 {
688 uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES;
689 psg_run(gen->psg, cur_target);
690 pico_pcm_run(gen->adpcm, cur_target);
691 }
692 psg_run(gen->psg, target);
693 pico_pcm_run(gen->adpcm, target);
694 }
695
696 static void adjust_int_cycle_pico(m68k_context *context, vdp_context *v_context)
697 {
698 genesis_context *gen = context->system;
699 if (context->sync_cycle - context->current_cycle > gen->max_cycles) {
700 context->sync_cycle = context->current_cycle + gen->max_cycles;
701 }
702 context->int_cycle = CYCLE_NEVER;
703 uint8_t mask = context->status & 0x7;
704 if (mask < 6) {
705 uint32_t next_vint = vdp_next_vint(v_context);
706 if (next_vint != CYCLE_NEVER) {
707 context->int_cycle = next_vint;
708 context->int_num = 6;
709 }
710 if (mask < 5) {
711 uint32_t next_hint = vdp_next_hint(v_context);
712 if (next_hint != CYCLE_NEVER) {
713 next_hint = next_hint < context->current_cycle ? context->current_cycle : next_hint;
714 if (next_hint < context->int_cycle) {
715 context->int_cycle = next_hint;
716 context->int_num = 5;
717
718 }
719 }
720 if (mask < 3) {
721 uint32_t next_pcm_int = pico_pcm_next_int(gen->adpcm);
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_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 = next_eint_port0 < next_eint_port1
731 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2)
732 : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2);
733 if (next_eint != CYCLE_NEVER) {
734 next_eint = next_eint < context->current_cycle ? context->current_cycle : next_eint;
735 if (next_eint < context->int_cycle) {
736 context->int_cycle = next_eint;
737 context->int_num = 2;
738 }
739 }
740 }
741 }
742 }
743 }
744 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) {
745 context->int_pending = INT_PENDING_NONE;
746 }
747 /*if (context->int_cycle != old_int_cycle) {
748 printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter);
749 old_int_cycle = context->int_cycle;
750 }*/
751
752 if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
753 context->target_cycle = context->current_cycle;
754 return;
755 }
756
757 context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle;
758 if (context->should_return || gen->header.enter_debugger || context->wp_hit) {
759 context->target_cycle = context->current_cycle;
760 } else if (context->target_cycle < context->current_cycle) {
761 //Changes to SR can result in an interrupt cycle that's in the past
762 //This can cause issues with the implementation of STOP though
763 context->target_cycle = context->current_cycle;
764 }
765 if (context->target_cycle == context->int_cycle) {
766 //Currently delays from Z80 access and refresh are applied only when we sync
767 //this can cause extra latency when it comes to interrupts
768 //to prevent this code forces some extra synchronization in the period immediately before an interrupt
769 if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev1) {
770 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev1;
771 } else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) {
772 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2;
773 } else {
774 context->target_cycle = context->sync_cycle = context->current_cycle;
775 }
776
777 }
778 }
779
684 static m68k_context* sync_components_pico(m68k_context * context, uint32_t address) 780 static m68k_context* sync_components_pico(m68k_context * context, uint32_t address)
685 { 781 {
686 genesis_context * gen = context->system; 782 genesis_context * gen = context->system;
687 vdp_context * v_context = gen->vdp; 783 vdp_context * v_context = gen->vdp;
688 if (gen->bus_busy) { 784 if (gen->bus_busy) {
690 } else { 786 } else {
691 gen_update_refresh(context); 787 gen_update_refresh(context);
692 } 788 }
693 789
694 uint32_t mclks = context->current_cycle; 790 uint32_t mclks = context->current_cycle;
695 psg_run(gen->psg, mclks); 791 sync_sound_pico(gen, mclks);
696 vdp_run_context(v_context, mclks); 792 vdp_run_context(v_context, mclks);
697 if (mclks >= gen->reset_cycle) { 793 if (mclks >= gen->reset_cycle) {
698 gen->reset_requested = 1; 794 gen->reset_requested = 1;
699 context->should_return = 1; 795 context->should_return = 1;
700 gen->reset_cycle = CYCLE_NEVER; 796 gen->reset_cycle = CYCLE_NEVER;
735 context->current_cycle -= deduction; 831 context->current_cycle -= deduction;
736 if (gen->psg->vgm) { 832 if (gen->psg->vgm) {
737 vgm_adjust_cycles(gen->psg->vgm, deduction); 833 vgm_adjust_cycles(gen->psg->vgm, deduction);
738 } 834 }
739 gen->psg->cycles -= deduction; 835 gen->psg->cycles -= deduction;
836 gen->adpcm->cycle -= deduction;
740 if (gen->reset_cycle != CYCLE_NEVER) { 837 if (gen->reset_cycle != CYCLE_NEVER) {
741 gen->reset_cycle -= deduction; 838 gen->reset_cycle -= deduction;
742 } 839 }
743 event_cycle_adjust(mclks, deduction); 840 event_cycle_adjust(mclks, deduction);
744 if (gen->expansion) { 841 if (gen->expansion) {
754 context->sync_cycle = gen->frame_end; 851 context->sync_cycle = gen->frame_end;
755 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); 852 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
756 if (!address && (gen->header.enter_debugger || gen->header.save_state)) { 853 if (!address && (gen->header.enter_debugger || gen->header.save_state)) {
757 context->sync_cycle = context->current_cycle + 1; 854 context->sync_cycle = context->current_cycle + 1;
758 } 855 }
759 adjust_int_cycle(context, v_context); 856 adjust_int_cycle_pico(context, v_context);
760 if (gen->reset_cycle < context->target_cycle) { 857 if (gen->reset_cycle < context->target_cycle) {
761 context->target_cycle = gen->reset_cycle; 858 context->target_cycle = gen->reset_cycle;
762 } 859 }
763 if (address) { 860 if (address) {
764 if (gen->header.enter_debugger || context->wp_hit) { 861 if (gen->header.enter_debugger || context->wp_hit) {
807 } 904 }
808 905
809 static m68k_context *int_ack(m68k_context *context) 906 static m68k_context *int_ack(m68k_context *context)
810 { 907 {
811 genesis_context * gen = context->system; 908 genesis_context * gen = context->system;
812 vdp_context * v_context = gen->vdp; 909 if (gen->header.type != SYSTEM_PICO || context->int_num > 4 || context->int_num < 3) {
813 //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); 910 vdp_context * v_context = gen->vdp;
814 vdp_run_context(v_context, context->current_cycle); 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);
815 vdp_int_ack(v_context); 912 vdp_run_context(v_context, context->current_cycle);
913 vdp_int_ack(v_context);
914 }
816 915
817 //the Genesis responds to these exclusively with !VPA which means its a slow 916 //the Genesis responds to these exclusively with !VPA which means its a slow
818 //6800 operation. documentation says these can take between 10 and 19 cycles. 917 //6800 operation. documentation says these can take between 10 and 19 cycles.
819 //actual results measurements seem to suggest it's actually between 9 and 18 918 //actual results measurements seem to suggest it's actually between 9 and 18
820 //Base 68K core has added 4 cycles for a normal int ack cycle already 919 //Base 68K core has added 4 cycles for a normal int ack cycle already
907 } 1006 }
908 } 1007 }
909 } else { 1008 } else {
910 context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context); 1009 context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context);
911 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); 1010 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
912 adjust_int_cycle(context, v_context); 1011 if (gen->header.type == SYSTEM_PICO) {
1012 adjust_int_cycle_pico(context, v_context);
1013 } else {
1014 adjust_int_cycle(context, v_context);
1015 }
913 } 1016 }
914 } else { 1017 } else {
915 fatal_error("Illegal write to HV Counter port %X\n", vdp_port); 1018 fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
916 } 1019 }
917 if (v_context->cycles != before_cycle) { 1020 if (v_context->cycles != before_cycle) {
1237 return vcontext; 1340 return vcontext;
1238 } 1341 }
1239 1342
1240 static void* pico_io_write_w(uint32_t location, void *vcontext, uint16_t value) 1343 static void* pico_io_write_w(uint32_t location, void *vcontext, uint16_t value)
1241 { 1344 {
1242 printf("Pico IO write.w %X - %X\n", location, value); 1345 uint32_t port = location & 0xFE;
1346 m68k_context *context = vcontext;
1347 genesis_context *gen = context->system;
1348 if (port == 0x10) {
1349 sync_sound_pico(gen, context->current_cycle);
1350 pico_pcm_data_write(gen->adpcm, value);
1351 printf("PICO ADPCM Data: %04X\n", value);
1352 if (context->int_num == 3) {
1353 adjust_int_cycle_pico(context, gen->vdp);
1354 }
1355 } else if (port == 0x12) {
1356 sync_sound_pico(gen, context->current_cycle);
1357 printf("PICO ADPCM Control: %04X\n", value);
1358 pico_pcm_ctrl_write(gen->adpcm, value);
1359 adjust_int_cycle_pico(context, gen->vdp);
1360 } else {
1361 return pico_io_write(location, vcontext, value);
1362 }
1243 return vcontext; 1363 return vcontext;
1244 } 1364 }
1245 1365
1246 #define FOREIGN 0x80 1366 #define FOREIGN 0x80
1247 #define HZ50 0x40 1367 #define HZ50 0x40
1374 1494
1375 static uint8_t pico_io_read(uint32_t location, void *vcontext) 1495 static uint8_t pico_io_read(uint32_t location, void *vcontext)
1376 { 1496 {
1377 m68k_context *m68k = vcontext; 1497 m68k_context *m68k = vcontext;
1378 genesis_context *gen = m68k->system; 1498 genesis_context *gen = m68k->system;
1499 uint16_t tmp;
1379 switch(location >> 1 & 0x7F) 1500 switch(location >> 1 & 0x7F)
1380 { 1501 {
1381 case 0: 1502 case 0:
1382 return gen->version_reg; 1503 return gen->version_reg;
1383 case 1: 1504 case 1:
1392 return gen->pico_pen_y; 1513 return gen->pico_pen_y;
1393 case 6: 1514 case 6:
1394 return gen->pico_page; 1515 return gen->pico_page;
1395 case 8: 1516 case 8:
1396 //printf("uPD7759 data read @ %u\n", m68k->current_cycle); 1517 //printf("uPD7759 data read @ %u\n", m68k->current_cycle);
1397 return 0xFF; 1518 sync_sound_pico(gen, m68k->current_cycle);
1519 tmp = pico_pcm_data_read(gen->adpcm);
1520 return (location & 1) ? tmp >> 8 : tmp;
1398 case 9: 1521 case 9:
1399 //printf("uPD7759 contro/status read @ %u\n", m68k->current_cycle); 1522 //printf("uPD7759 contro/status read @ %u\n", m68k->current_cycle);
1523 sync_sound_pico(gen, m68k->current_cycle);
1524 tmp = pico_pcm_ctrl_read(gen->adpcm);
1525 return (location & 1) ? tmp >> 8 : tmp;
1400 return 0; 1526 return 0;
1401 default: 1527 default:
1402 printf("Unknown Pico IO read %X @ %u\n", location, m68k->current_cycle); 1528 printf("Unknown Pico IO read %X @ %u\n", location, m68k->current_cycle);
1403 return 0xFF; 1529 return 0xFF;
1404 } 1530 }
1406 1532
1407 static uint16_t pico_io_read_w(uint32_t location, void *vcontext) 1533 static uint16_t pico_io_read_w(uint32_t location, void *vcontext)
1408 { 1534 {
1409 m68k_context *m68k = vcontext; 1535 m68k_context *m68k = vcontext;
1410 genesis_context *gen = m68k->system; 1536 genesis_context *gen = m68k->system;
1537 uint32_t port = location & 0xFE;
1538 if (port == 0x10) {
1539 sync_sound_pico(gen, m68k->current_cycle);
1540 return pico_pcm_data_read(gen->adpcm);
1541 } else if (port == 0x12) {
1542 sync_sound_pico(gen, m68k->current_cycle);
1543 return pico_pcm_ctrl_read(gen->adpcm);
1544 }
1411 uint16_t value = pico_io_read(location, vcontext); 1545 uint16_t value = pico_io_read(location, vcontext);
1412 return value | (value << 8); 1546 return value | (value << 8);
1413 } 1547 }
1414 1548
1415 static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) 1549 static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value)
1776 gen->header.enter_debugger = 0; 1910 gen->header.enter_debugger = 0;
1777 #ifndef IS_LIB 1911 #ifndef IS_LIB
1778 insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); 1912 insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
1779 #endif 1913 #endif
1780 } 1914 }
1781 adjust_int_cycle(gen->m68k, gen->vdp); 1915 if (gen->header.type == SYSTEM_PICO) {
1916 adjust_int_cycle_pico(gen->m68k, gen->vdp);
1917 } else {
1918 adjust_int_cycle(gen->m68k, gen->vdp);
1919 }
1782 start_68k_context(gen->m68k, pc); 1920 start_68k_context(gen->m68k, pc);
1783 } else { 1921 } else {
1784 if (gen->header.enter_debugger) { 1922 if (gen->header.enter_debugger) {
1785 gen->header.enter_debugger = 0; 1923 gen->header.enter_debugger = 0;
1786 #ifndef IS_LIB 1924 #ifndef IS_LIB
1959 if (gen->header.type == SYSTEM_GENESIS) { 2097 if (gen->header.type == SYSTEM_GENESIS) {
1960 z80_options_free(gen->z80->Z80_OPTS); 2098 z80_options_free(gen->z80->Z80_OPTS);
1961 free(gen->z80); 2099 free(gen->z80);
1962 free(gen->zram); 2100 free(gen->zram);
1963 } 2101 }
1964 if (gen->header.type != SYSTEM_PICO) { 2102 if (gen->header.type == SYSTEM_PICO) {
2103 pico_pcm_free(gen->adpcm);
2104 free(gen->adpcm);
2105 } else {
1965 ym_free(gen->ym); 2106 ym_free(gen->ym);
1966 } 2107 }
1967 psg_free(gen->psg); 2108 psg_free(gen->psg);
1968 free(gen->header.save_dir); 2109 free(gen->header.save_dir);
1969 free_rom_info(&gen->header.info); 2110 free_rom_info(&gen->header.info);
2224 if (debug_view < DEBUG_OSCILLOSCOPE) { 2365 if (debug_view < DEBUG_OSCILLOSCOPE) {
2225 vdp_toggle_debug_view(gen->vdp, debug_view); 2366 vdp_toggle_debug_view(gen->vdp, debug_view);
2226 } else if (debug_view == DEBUG_OSCILLOSCOPE) { 2367 } else if (debug_view == DEBUG_OSCILLOSCOPE) {
2227 if (gen->psg->scope) { 2368 if (gen->psg->scope) {
2228 oscilloscope *scope = gen->psg->scope; 2369 oscilloscope *scope = gen->psg->scope;
2229 if (gen->header.type != SYSTEM_PICO) { 2370 if (gen->header.type == SYSTEM_PICO) {
2371 gen->adpcm->scope = NULL;
2372 } else {
2230 gen->ym->scope = NULL; 2373 gen->ym->scope = NULL;
2231 } 2374 }
2232 gen->psg->scope = NULL; 2375 gen->psg->scope = NULL;
2233 if (gen->expansion) { 2376 if (gen->expansion) {
2234 segacd_context *cd = gen->expansion; 2377 segacd_context *cd = gen->expansion;
2235 cd->pcm.scope = NULL; 2378 cd->pcm.scope = NULL;
2236 } 2379 }
2237 scope_close(scope); 2380 scope_close(scope);
2238 } else { 2381 } else {
2239 oscilloscope *scope = create_oscilloscope(); 2382 oscilloscope *scope = create_oscilloscope();
2240 if (gen->header.type != SYSTEM_PICO) { 2383 if (gen->header.type == SYSTEM_PICO) {
2384 pico_pcm_enable_scope(gen->adpcm, scope, gen->normal_clock);
2385 } else {
2241 ym_enable_scope(gen->ym, scope, gen->normal_clock); 2386 ym_enable_scope(gen->ym, scope, gen->normal_clock);
2242 } 2387 }
2243 psg_enable_scope(gen->psg, scope, gen->normal_clock); 2388 psg_enable_scope(gen->psg, scope, gen->normal_clock);
2244 if (gen->expansion) { 2389 if (gen->expansion) {
2245 segacd_context *cd = gen->expansion; 2390 segacd_context *cd = gen->expansion;
2911 3056
2912 render_set_video_standard((gen->version_reg & 0x60) == 0x20 ? VID_PAL : VID_NTSC); 3057 render_set_video_standard((gen->version_reg & 0x60) == 0x20 ? VID_PAL : VID_NTSC);
2913 3058
2914 gen->psg = calloc(1, sizeof(psg_context)); 3059 gen->psg = calloc(1, sizeof(psg_context));
2915 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); 3060 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG);
3061
3062 gen->adpcm = calloc(1, sizeof(pico_pcm));
3063 pico_pcm_init(gen->adpcm, gen->master_clock, 42);
3064
2916 gen->work_ram = calloc(2, RAM_WORDS); 3065 gen->work_ram = calloc(2, RAM_WORDS);
2917 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) 3066 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval))
2918 { 3067 {
2919 srand(time(NULL)); 3068 srand(time(NULL));
2920 for (int i = 0; i < RAM_WORDS; i++) 3069 for (int i = 0; i < RAM_WORDS; i++)