diff genesis.c @ 2558:3f58fec775df

Initial work on YMF262 (aka OPL3) emulation
author Michael Pavone <pavone@retrodev.com>
date Sun, 19 Jan 2025 00:31:16 -0800
parents 6f1eebc0a90b
children f0ace2494df6
line wrap: on
line diff
--- a/genesis.c	Thu Jan 16 22:42:09 2025 -0800
+++ b/genesis.c	Sun Jan 19 00:31:16 2025 -0800
@@ -709,13 +709,16 @@
 		psg_run(gen->psg, cur_target);
 		pico_pcm_run(gen->adpcm, cur_target);
 		if (gen->ymz) {
+			//FIXME: These have a separate crystal
 			ymz263b_run(gen->ymz, cur_target);
+			ymf262_run(gen->opl, cur_target);
 		}
 	}
 	psg_run(gen->psg, target);
 	pico_pcm_run(gen->adpcm, target);
 	if (gen->ymz) {
 		ymz263b_run(gen->ymz, target);
+		ymf262_run(gen->opl, target);
 	}
 }
 
@@ -872,6 +875,7 @@
 			gen->adpcm->cycle -= deduction;
 			if (gen->ymz) {
 				gen->ymz->cycle -= deduction;
+				ymf262_adjust_cycles(gen->opl, deduction);
 			}
 			if (gen->reset_cycle != CYCLE_NEVER) {
 				gen->reset_cycle -= deduction;
@@ -1603,6 +1607,7 @@
 	uint8_t ret;
 	m68k_context *m68k = vcontext;
 	genesis_context *gen = m68k->system;
+	//FIXME: Copera sound hardware has a separate clock
 	switch (location & 0xFF)
 	{
 	case 1:
@@ -1618,6 +1623,10 @@
 		ret = ymz263b_data_read(gen->ymz, location & 4);
 		printf("Copera YMZ263 Data read - %X: %X\n", location, ret);
 		return ret;
+	case 0x28:
+		ret = ymf262_read_status(gen->opl, m68k->cycles, 0);
+		printf("Copera YMF262 Status read - %X: %X\n", location, ret);
+		return ret;
 	default:
 		printf("Unhandled Copera 8-bit read %X\n", location);
 		return 0xFF;
@@ -1634,6 +1643,7 @@
 {
 	m68k_context *m68k = vcontext;
 	genesis_context *gen = m68k->system;
+	//FIXME: Copera sound hardware has a separate clock
 	switch (location & 0xFF)
 	{
 	case 1:
@@ -1652,9 +1662,17 @@
 	case 0x24:
 	case 0x34:
 		printf("Copera YMF262 Address Part #%d write - %X: %X\n", ((location >> 4) & 1) + 1, location, value);
+		ymf262_run(gen->opl, m68k->cycles);
+		if (location & 0x10) {
+			ymf262_address_write_part2(gen->opl, value);
+		} else {
+			ymf262_address_write_part1(gen->opl, value);
+		}
 		break;
 	case 0x28:
 		printf("Copera YMF262 Data write - %X: %X\n", location, value);
+		ymf262_run(gen->opl, m68k->cycles);
+		ymf262_data_write(gen->opl, value);
 		break;
 	case 0x40:
 		//Bit 4 = SCI
@@ -1906,6 +1924,7 @@
 		}
 		if (context->ymz) {
 			ymz263b_adjust_master_clock(context->ymz, context->master_clock);
+			ymf262_adjust_master_clock(context->opl, context->master_clock);
 		}
 		pico_pcm_adjust_master_clock(context->adpcm, context->master_clock);
 	}
@@ -2250,6 +2269,7 @@
 		if (gen->ymz) {
 			ymz263b_free(gen->ymz);
 			free(gen->ymz);
+			ymf262_free(gen->opl);
 		}
 	} else {
 		ym_free(gen->ym);
@@ -2495,6 +2515,9 @@
 			ym_vgm_log(gen->ym, gen->normal_clock, vgm);
 		} else {
 			sync_sound_pico(gen, vgm->last_cycle);
+			if (gen->opl) {
+				ymf262_vgm_log(gen->opl, gen->normal_clock, vgm);
+			}
 		}
 		psg_vgm_log(gen->psg, gen->normal_clock, vgm);
 		gen->header.vgm_logging = 1;
@@ -3230,7 +3253,10 @@
 		//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
+		//FIXME: Copera does actually have a separate crystal for these
 		ymz263b_init(gen->ymz, gen->master_clock, 3);
+		gen->opl = calloc(1, sizeof(*gen->opl));
+		ymf262_init(gen->opl, gen->master_clock, 3, ym_opts);
 	}
 	
 	gen->work_ram = calloc(2, RAM_WORDS);