changeset 1808:ce6881d64eef

Operator results should be delayed by one sample when used as a modulator in some cases based on relative execution time and pipeline length
author Michael Pavone <pavone@retrodev.com>
date Wed, 27 Mar 2019 22:04:54 -0700
parents a218c253fcb3
children c2057d79998c
files ym2612.c ym2612.h
diffstat 2 files changed, 24 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/ym2612.c	Tue Mar 26 23:55:41 2019 -0700
+++ b/ym2612.c	Wed Mar 27 22:04:54 2019 -0700
@@ -481,8 +481,7 @@
 				if (operator->mod_src[0]) {
 					mod = *operator->mod_src[0];
 					if (operator->mod_src[1]) {
-						mod += *
-						operator->mod_src[1];
+						mod += *operator->mod_src[1];
 					}
 					mod >>= YM_MOD_SHIFT;
 				}
@@ -540,6 +539,8 @@
 			}
 			if (op % 4 == 0) {
 				chan->op1_old = operator->output;
+			} else if (op % 4 == 2) {
+				chan->op2_old = operator->output;
 			}
 			operator->output = output;
 			//Update the channel output if we've updated all operators
@@ -712,6 +713,7 @@
 		inc = channel->fnum;
 		if (channel->pms) {
 			inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step];
+			inc &= 0xFFF;
 		}
 		if (!channel->block) {
 			inc >>= 1;
@@ -928,6 +930,8 @@
 				{
 				case 0:
 					//operator 3 modulated by operator 2
+					//this uses a special op2 result reg on HW, but that reg will have the most recent
+					//result from op2 when op3 starts executing
 					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
 					context->operators[channel*4+1].mod_src[1] = NULL;
 					
@@ -940,7 +944,11 @@
 					break;
 				case 1:
 					//operator 3 modulated by operator 1+2
-					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output;
+					//op1 starts executing before this, but due to pipeline length the most current result is
+					//not available and instead the previous result is used
+					context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
+					//this uses a special op2 result reg on HW, but that reg will have the most recent
+					//result from op2 when op3 starts executing
 					context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output;
 					
 					//operator 2 unmodulated
@@ -952,6 +960,8 @@
 					break;
 				case 2:
 					//operator 3 modulated by operator 2
+					//this uses a special op2 result reg on HW, but that reg will have the most recent
+					//result from op2 when op3 starts executing
 					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
 					context->operators[channel*4+1].mod_src[1] = NULL;
 					
@@ -959,6 +969,8 @@
 					context->operators[channel*4+2].mod_src[0] = NULL;
 					
 					//operator 4 modulated by operator 1+3
+					//this uses a special op1 result reg on HW, but that reg will have the most recent
+					//result from op1 when op4 starts executing
 					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
 					context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
 					break;
@@ -971,7 +983,9 @@
 					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
 					
 					//operator 4 modulated by operator 2+3
-					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+2].output;
+					//op2 starts executing before this, but due to pipeline length the most current result is
+					//not available and instead the previous result is used
+					context->operators[channel*4+3].mod_src[0] = &context->channels[channel].op2_old;
 					context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
 					break;
 				case 4:
@@ -988,13 +1002,17 @@
 					break;
 				case 5:
 					//operator 3 modulated by operator 1
-					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+0].output;
+					//op1 starts executing before this, but due to pipeline length the most current result is
+					//not available and instead the previous result is used
+					context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
 					context->operators[channel*4+1].mod_src[1] = NULL;
 					
 					//operator 2 modulated by operator 1
 					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
 					
 					//operator 4 modulated by operator 1
+					//this uses a special op1 result reg on HW, but that reg will have the most recent
+					//result from op1 when op4 starts executing
 					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
 					context->operators[channel*4+3].mod_src[1] = NULL;
 					break;
--- a/ym2612.h	Tue Mar 26 23:55:41 2019 -0700
+++ b/ym2612.h	Wed Mar 27 22:04:54 2019 -0700
@@ -39,6 +39,7 @@
 	uint16_t fnum;
 	int16_t  output;
 	int16_t  op1_old;
+	int16_t  op2_old;
 	uint8_t  block_fnum_latch;
 	uint8_t  block;
 	uint8_t  keycode;