Added workaround in FMOPL for the pathological case where a note was turned off

while still at the very beginning of the "attack" phase. This is the very
lowest point on the attack curve, yet it would continue from the beginning of
the release curve, i.e. its very highest point. This is what caused Kyra to
often play low-frequency notes at the very beginning of a new song. (That, and
a truly bizarre function for initialising the channels.)

The proper fix would be to locate the correct point on the release curve and
continue from there. For now, though, only handle the trivial case.

svn-id: r21302
This commit is contained in:
Torbjörn Andersson 2006-03-14 23:01:44 +00:00
parent 59b6f0f715
commit 839b5d3e86
2 changed files with 38 additions and 10 deletions

View File

@ -808,18 +808,17 @@ void AdlibDriver::unkOutput2(uint8 chan) {
// including the two most significant frequency bit, and the octave -
// set to zero.
//
// This is very strange behaviour, and appears to be the cause of the
// bug where low-frequent notes are played at the beginning of a new
// sound. However, this is what the original does, and the bug does not
// seem to happen with current versions of the FMOPL code.
// This is very strange behaviour, and causes problems with the ancient
// FMOPL code we borrowed from AdPlug. I've added a workaround. See
// fmopl.cpp for more details.
//
// Unfortunately, we cannot use more recent versions because of license
// incompatibilities.
// More recent versions of the MAME FMOPL don't seem to have this
// problem, but cannot currently be used because of licensing and
// performance issues.
//
// Ken Silverman's Adlib emulator (which can be found on his Web page -
// http://www.advsys.net/ken - and as part of AdPlug) also seems to be
// proof against this particular bug, but is apparently not as feature
// complete as MAME's.
// immune, but is apparently not as feature complete as MAME's.
writeOPL(0xB0 + chan, 0x20);
}

View File

@ -304,12 +304,41 @@ inline void OPL_KEYON(OPL_SLOT *SLOT) {
inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
if( SLOT->evm > ENV_MOD_RR) {
/* set envelope counter from envleope output */
SLOT->evm = ENV_MOD_RR;
if( !(SLOT->evc & EG_DST) )
// WORKAROUND: The Kyra engine does something very strange when
// starting a new song. For each channel:
//
// * The release rate is set to "fastest".
// * Any note is keyed off.
// * A very low-frequency note is keyed on.
//
// Usually, what happens next is that the real notes is keyed
// on immediately, in which case there's no problem.
//
// However, if the note is again keyed off (because the channel
// begins on a rest rather than a note), the envelope counter
// was moved from the very lowest point on the attack curve to
// the very highest point on the release curve.
//
// Again, this might not be a problem, if the release rate is
// still set to "fastest". But in many cases, it had already
// been increased. And, possibly because of inaccuracies in the
// envelope generator, that would cause the note to "fade out"
// for quite a long time.
//
// What we really need is a way to find the correct starting
// point for the envelope counter, and that may be what the
// commented-out line below is meant to do. For now, simply
// handle the pathological case.
if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
SLOT->evc = EG_DED;
else if( !(SLOT->evc & EG_DST) )
//SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
SLOT->evc = EG_DST;
SLOT->eve = EG_DED;
SLOT->evs = SLOT->evsr;
SLOT->evm = ENV_MOD_RR;
}
}