diff ym2612.c @ 2243:0d1d5dccdd28

Initial implementation of oscilloscope debug view
author Michael Pavone <pavone@retrodev.com>
date Tue, 22 Nov 2022 17:57:02 -0800
parents cfd53c94fffb
children 74112041b2c7
line wrap: on
line diff
--- a/ym2612.c	Wed Sep 21 23:16:39 2022 -0700
+++ b/ym2612.c	Tue Nov 22 17:57:02 2022 -0800
@@ -156,9 +156,11 @@
 	memset(context->part2_regs, 0, sizeof(context->part2_regs));
 	memset(context->operators, 0, sizeof(context->operators));
 	FILE* savedlogs[NUM_CHANNELS];
+	uint8_t saved_scope_channel[NUM_CHANNELS];
 	for (int i = 0; i < NUM_CHANNELS; i++)
 	{
 		savedlogs[i] = context->channels[i].logfile;
+		saved_scope_channel[i] = context->channels[i].scope_channel;
 	}
 	memset(context->channels, 0, sizeof(context->channels));
 	memset(context->ch3_supp, 0, sizeof(context->ch3_supp));
@@ -179,6 +181,7 @@
 	for (int i = 0; i < NUM_CHANNELS; i++) {
 		context->channels[i].lr = 0xC0;
 		context->channels[i].logfile = savedlogs[i];
+		context->channels[i].scope_channel = saved_scope_channel[i];
 		if (i < 3) {
 			context->part1_regs[REG_LR_AMS_PMS - YM_PART1_START + i] = 0xC0;
 		} else {
@@ -496,7 +499,9 @@
 		ym_operator * operator = context->operators + op;
 		ym_channel * chan = context->channels + channel;
 		uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
+		uint32_t old_phase = operator->phase_counter;
 		operator->phase_counter += operator->phase_inc;//ym_calc_phase_inc(context, operator, op);
+		operator->phase_overflow = (old_phase & 0xFFFFF) > (operator->phase_counter & 0xFFFFF);
 		int16_t mod = 0;
 		if (op & 3) {
 			if (operator->mod_src[0]) {
@@ -568,21 +573,27 @@
 		if (op % 4 == 3) {
 			if (chan->algorithm < 4) {
 				chan->output = operator->output;
+				chan->phase_overflow = operator->phase_overflow;
 			} else if(chan->algorithm == 4) {
-				chan->output = operator->output + context->operators[channel * 4 + 2].output;
+				ym_operator *other_op = context->operators + channel * 4 + 2;
+				chan->output = operator->output + other_op->output;
+				if (operator->phase_inc < other_op->phase_inc) {
+					chan->phase_overflow = operator->phase_overflow;
+				} else {
+					chan->phase_overflow = other_op->phase_overflow;
+				}
 			} else {
 				output = 0;
+				uint32_t lowest_phase_inc = 0xFFFFFFFF;
 				for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
 					output += context->operators[op].output;
+					if (context->operators[op].phase_inc < lowest_phase_inc) {
+						lowest_phase_inc = context->operators[op].phase_inc;
+						chan->phase_overflow = context->operators[op].phase_overflow;
+					}
 				}
 				chan->output = output;
 			}
-			if (first_key_on) {
-				int16_t value = context->channels[channel].output & 0x3FE0;
-				if (value & 0x2000) {
-					value |= 0xC000;
-				}
-			}
 		}
 		//puts("operator update done");
 	}
@@ -611,6 +622,9 @@
 		if (context->channels[i].logfile) {
 			fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
 		}
+		if (context->scope) {
+			scope_add_sample(context->scope, context->channels[i].scope_channel, value, context->channels[i].phase_overflow);
+		}
 		if (context->channels[i].lr & 0x80) {
 			left += (value * context->volume_mult) / context->volume_div;
 		} else if (context->zero_offset) {
@@ -1382,3 +1396,21 @@
 		context->last_status_cycle = context->write_cycle;
 	}
 }
+
+void ym_enable_scope(ym2612_context *context, oscilloscope *scope)
+{
+	static const char *names[] = {
+		"YM2612 #1",
+		"YM2612 #2",
+		"YM2612 #3",
+		"YM2612 #4",
+		"YM2612 #5",
+		"YM2612 #6"
+	};
+	context->scope = scope;
+	for (int i = 0; i < NUM_CHANNELS; i++)
+	{
+		//TODO: calculate actual sample rate based on current clock settings
+		context->channels[i].scope_channel = scope_add_channel(scope, names[i], 53267);
+	}
+}