Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/genesis.c Wed Feb 21 23:42:19 2024 -0800 +++ b/genesis.c Fri Feb 23 01:16:38 2024 -0800 @@ -688,9 +688,15 @@ uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES; psg_run(gen->psg, cur_target); pico_pcm_run(gen->adpcm, cur_target); + if (gen->ymz) { + ymz263b_run(gen->ymz, cur_target); + } } psg_run(gen->psg, target); pico_pcm_run(gen->adpcm, target); + if (gen->ymz) { + ymz263b_run(gen->ymz, target); + } } static void adjust_int_cycle_pico(m68k_context *context, vdp_context *v_context) @@ -717,13 +723,8 @@ } } - if (mask < 3) { - uint32_t next_pcm_int = pico_pcm_next_int(gen->adpcm); - if (next_pcm_int != CYCLE_NEVER && next_pcm_int < context->int_cycle) { - context->int_cycle = next_pcm_int; - context->int_num = 3; - } - if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN) && gen->header.type == SYSTEM_GENESIS) { + if (mask < 4) { + if (v_context->regs[REG_MODE_3] & BIT_EINT_EN) { uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); @@ -738,6 +739,21 @@ } } } + if (mask < 3) { + uint32_t next_pcm_int = pico_pcm_next_int(gen->adpcm); + if (next_pcm_int != CYCLE_NEVER && next_pcm_int < context->int_cycle) { + context->int_cycle = next_pcm_int; + context->int_num = 3; + } + + if (mask < 2 && gen->ymz) { + uint32_t ymz_int = ymz263b_next_int(gen->ymz); + if (ymz_int < context->int_cycle) { + context->int_cycle = ymz_int; + context->int_num = 2; + } + } + } } } } @@ -834,6 +850,9 @@ } gen->psg->cycles -= deduction; gen->adpcm->cycle -= deduction; + if (gen->ymz) { + gen->ymz->cycle -= deduction; + } if (gen->reset_cycle != CYCLE_NEVER) { gen->reset_cycle -= deduction; } @@ -906,7 +925,7 @@ static m68k_context *int_ack(m68k_context *context) { genesis_context * gen = context->system; - if ((gen->header.type != SYSTEM_PICO && gen->header.type != SYSTEM_COPERA) || context->int_num > 4 || context->int_num < 3) { + if ((gen->header.type != SYSTEM_PICO && gen->header.type != SYSTEM_COPERA) || context->int_num > 3) { vdp_context * v_context = gen->vdp; //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); vdp_run_context(v_context, context->current_cycle); @@ -1561,8 +1580,28 @@ static uint8_t copera_io_read(uint32_t location, void *vcontext) { - printf("Unhandled Copera 8-bit read %X\n", location); - return 0xFF; + uint8_t ret; + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + switch (location & 0xFF) + { + case 1: + case 5: + ymz263b_run(gen->ymz, m68k->current_cycle); + ret = ymz263b_status_read(gen->ymz); + printf("Copera YMZ263 Status read - %X: %X\n", location, ret); + adjust_int_cycle_pico(gen->m68k, gen->vdp); + return ret; + case 3: + case 7: + ymz263b_run(gen->ymz, m68k->current_cycle); + ret = ymz263b_data_read(gen->ymz, location & 4); + printf("Copera YMZ263 Data read - %X: %X\n", location, ret); + return ret; + default: + printf("Unhandled Copera 8-bit read %X\n", location); + return 0xFF; + } } static void* copera_io_write_w(uint32_t location, void *vcontext, uint16_t value) @@ -1573,22 +1612,29 @@ static void* copera_io_write(uint32_t location, void *vcontext, uint8_t value) { + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; switch (location & 0xFF) { case 1: case 5: + ymz263b_run(gen->ymz, m68k->current_cycle); printf("Copera YMZ263 Address write - %X: %X\n", location, value); + ymz263b_address_write(gen->ymz, value); break; case 3: case 7: + ymz263b_run(gen->ymz, m68k->current_cycle); printf("Copera YMZ263 Channel #%d Data write - %X: %X\n", ((location & 4) >> 2) + 1, location, value); + ymz263b_data_write(gen->ymz, location & 4, value); + adjust_int_cycle_pico(gen->m68k, gen->vdp); break; case 0x24: case 0x34: - printf("Copera YMF263 Address Part #%d write - %X: %X\n", ((location >> 4) & 1) + 1, location, value); + printf("Copera YMF262 Address Part #%d write - %X: %X\n", ((location >> 4) & 1) + 1, location, value); break; case 0x28: - printf("Copera YMF263 Data write - %X: %X\n", location, value); + printf("Copera YMF262 Data write - %X: %X\n", location, value); break; case 0x40: //Bit 4 = SCI @@ -2159,6 +2205,10 @@ if (gen->header.type == SYSTEM_PICO || gen->header.type == SYSTEM_COPERA) { pico_pcm_free(gen->adpcm); free(gen->adpcm); + if (gen->ymz) { + //TODO: call cleanup function once it exists + free(gen->ymz); + } } else { ym_free(gen->ym); } @@ -3125,6 +3175,14 @@ gen->adpcm = calloc(1, sizeof(pico_pcm)); pico_pcm_init(gen->adpcm, gen->master_clock, 42); + if (stype == SYSTEM_COPERA) { + gen->ymz = calloc(1, sizeof(*gen->ymz)); + //This divider is just a guess, PCB diagram in MAME shows no other crystal + //Datasheet says the typical clock is 16.9344 MHz + //Master clock / 3 is 17.897725 MHz which is reasonably close + ymz263b_init(gen->ymz, 3); + } + gen->work_ram = calloc(2, RAM_WORDS); if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) {