changeset 852:5de8759b87af

Fix some bugs in the attack phase and sustain level in the envelope generator
author Michael Pavone <pavone@retrodev.com>
date Mon, 02 Nov 2015 22:33:54 -0800
parents b10cf2c921ad
children 2d474efb4629
files ym2612.c
diffstat 1 files changed, 8 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/ym2612.c	Sun Nov 01 20:44:12 2015 -0800
+++ b/ym2612.c	Mon Nov 02 22:33:54 2015 -0800
@@ -298,15 +298,14 @@
 			}
 			if (!(env_cyc & ((1 << cycle_shift) - 1))) {
 				uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
-				//envelope value is 10-bits, but it will be used as a 4.8 value
-				uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2;
+				uint16_t envelope_inc = rate_table[rate * 8 + update_cycle];
 				if (operator->env_phase == PHASE_ATTACK) {
 					//this can probably be optimized to a single shift rather than a multiply + shift
 					if (first_key_on) {
 						dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc);
 					}
 					uint16_t old_env = operator->envelope;
-					operator->envelope += (~operator->envelope * envelope_inc) >> 4;
+					operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC;
 					if (operator->envelope > old_env) {
 						//Handle overflow
 						operator->envelope = 0;
@@ -319,7 +318,8 @@
 						dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc,
 							operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release"));
 					}
-					operator->envelope += envelope_inc;
+					//envelope value is 10-bits, but it will be used as a 4.8 value
+					operator->envelope += envelope_inc << 2;
 					//clamp to max attenuation value
 					if (operator->envelope > MAX_ENVELOPE) {
 						operator->envelope = MAX_ENVELOPE;
@@ -752,7 +752,10 @@
 				break;
 			case REG_S_LVL_R_RATE:
 				operator->rates[PHASE_RELEASE] = (value & 0xF) << 1 | 1;
-				operator->sustain_level = (value & 0xF0) << 4;
+				operator->sustain_level = (value & 0xF0) << 3;
+				if (operator->sustain_level == 0x780) {
+					operator->sustain_level = MAX_ENVELOPE;
+				}
 				break;
 			}
 		}