From f2e2d4e0b46b5489ae7e0cb7b8ac2974157e4768 Mon Sep 17 00:00:00 2001 From: Kamil Patecki Date: Mon, 11 Aug 2025 23:44:06 +0200 Subject: [PATCH] Use raw pitch in envelope column --- src/engine/platform/ay.cpp | 25 ++++++++++++++++++++----- src/engine/platform/ay.h | 7 ++++++- src/engine/platform/ym2203.cpp | 3 +++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index bfcb242fe..45fd6cffc 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -674,11 +674,25 @@ void DivPlatformAY8910::tick(bool sysTick) { ayEnvPeriod=chan[3].std.ex5.val<<8; } else if ((chan[3].freqChanged && chan[3].active) || chan[3].keyOn) { - chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,chan[3].fixedArp?chan[3].baseNoteOverride:chan[3].arpOff,chan[3].fixedArp,true,0,chan[3].pitch2,chipClock*16,CHIP_DIVIDER); - if (chan[3].freq<0) chan[3].freq=0; - if (chan[3].freq>65535*256) chan[3].freq=65535*256; - ayEnvPeriod=chan[3].freq; - chan[3].freqChanged=false; + if (envRawMode) { + // Compute base without pitch2, then apply pitch2 directly to the raw envelope period + int baseFreq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,chan[3].fixedArp?chan[3].baseNoteOverride:chan[3].arpOff,chan[3].fixedArp,true,0,0,chipClock*16,CHIP_DIVIDER); + if (baseFreq<0) baseFreq=0; + if (baseFreq>65535*256) baseFreq=65535*256; + // Apply pitch2 later as raw offset in the same fixed-point scale (8 fractional bits) + long adjusted=(long)baseFreq + ((long)chan[3].pitch2<<8); + if (adjusted<0) adjusted=0; + if (adjusted>(long)65535*256) adjusted=(long)65535*256; + chan[3].freq=(int)adjusted; + ayEnvPeriod=chan[3].freq; + chan[3].freqChanged=false; + } else { + chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,chan[3].fixedArp?chan[3].baseNoteOverride:chan[3].arpOff,chan[3].fixedArp,true,0,chan[3].pitch2,chipClock*16,CHIP_DIVIDER); + if (chan[3].freq<0) chan[3].freq=0; + if (chan[3].freq>65535*256) chan[3].freq=65535*256; + ayEnvPeriod=chan[3].freq; + chan[3].freqChanged=false; + } } if (chan[3].keyOn) chan[3].keyOn=false; if (chan[3].keyOff) chan[3].keyOff=false; @@ -1317,6 +1331,7 @@ void DivPlatformAY8910::setFlags(const DivConfig& flags) { stereo=flags.getBool("stereo",false); stereoSep=flags.getInt("stereoSep",0)&255; extendedSsg=false; + envRawMode=flags.getBool("envRawMode",false); switch (flags.getInt("panLaw",0)) { case 1: centerVol=sqrtf((stereoSep+256)/512.f)*256.f; diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index db08f8ee2..db3180b96 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -141,6 +141,10 @@ class DivPlatformAY8910: public DivDispatch { unsigned char dacRateDiv; bool stereo, sunsoft, intellivision, clockSel, yamaha; + // When true, the AY "envelope column" uses raw register values instead of + // converting linear pitch/note values into envelope frequency. Intended for + // embedded AY inside chips like YM2203. + bool envRawMode; bool ioPortA, ioPortB; unsigned char portAVal, portBVal; @@ -202,6 +206,7 @@ class DivPlatformAY8910: public DivDispatch { extMode(useExtMode), extClock(eclk), extDiv(ediv), - dacRateDiv(ddiv) {} + dacRateDiv(ddiv), + envRawMode(false) {} }; #endif diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 0265634db..afc0d4e8e 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -1472,6 +1472,9 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) { ayFlags.set("stereo",stereo); ayFlags.set("stereoSep",stereoSep); ayFlags.set("panLaw",flags.getInt("panLaw",0)); + // AY inside YM2203 should treat envelope column values as raw register values + // rather than linear pitch-derived values. + ayFlags.set("envRawMode",true); if (useCombo==2) { rate=chipClock/(fmDivBase*2); } else {